home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Developer CD v1.2
/
amidev_cd_12.iso
/
devcon
/
milan_1991
/
devcon91.2
/
network
/
socket
/
examples
/
server1.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-01
|
6KB
|
218 lines
/*
** server.c
**
** Written by Dale Larson, Software Engineer, Commodore-Amiga, Inc.
** Copyright 1991, Commodore-Amiga, Inc.
** Permission to use granted provided this notice remains intact.
**
** This is a simple version of the ncopy server. It processes only one
** request at a time. This is adequate for a server which sees light or
** infrequent usage, but can lead to unacceptable delays for a server which
** sees heavy or even moderate trafic. It also will cause problems if the
** user copies a file from a remote machine to the same remote machine
** (i.e. ncopy sprite!ram:x sprite!work:y).
**
** You should study and understand this server before you look at
** server2.c, which is significantly more complex.
**
** This server has no provisions for exiting.
** A system requester will pop up if the server recieves a request to
** read/write to/from a device a non-existant device.
*/
#include "ncopy.h"
struct Library *SockBase;
#define MAXSOCKS 10
char vers[] = "\0$VER: server1 1.0 (25.02.91)";
void handle_request(int s);
void send_file(int s, BPTR file);
void get_file(int s, BPTR file);
/*
** main()
**
** Get a socket, bind a name to it, express a willingness to accept
** connections to it (listen) then wait to actually accept connections.
** Once a connection has been accepted, give the handler function the
** socket which accept() connected to a remote machine so that the handler
** function can chat with the remote machine. When the handler returns,
** go back to waiting to accept connections.
*/
main(int argc, char **argv)
{
struct sockaddr_in sin; /* socket address (internet) to establish */
int s, ns; /* socket and new socket */
size_t len = sizeof(sin);
/* Open Shared Socket library:
*/
if(SockBase = OpenLibrary( "inet:libs/socket.library", 0L ))
{
setup_sockets( MAXSOCKS, &errno );
}else
{
puts("Can't open socket.library.");
exit(RETURN_ERROR);
}
/*
** Initialize a socket.
*/
if( (s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket");
exit(RETURN_ERROR);
}
/*
** Bind name to socket.
** Since we got sin off the stack, it could contain anything, and so
** we zero it before initializing it.
*/
bzero(&sin, (int)len);
sin.sin_family = AF_INET;
/*
** While prototyping a program, pick an unused port number above
** 1024 like I did here. For a real program, assign a name and a
** port number above 1024 and stick it in inet:db/servers on all
** machines which will use the application. That way the user can
** reconfigure port numbers used by new applications if necessary.
** You can modify the server to get the port number from the
** database by using code like this (instead of "sin.sin_port=
** htons(6666)" below):
**
** struct servent *servptr;
** char serv[] = "servicename";
**
** if( (servptr = getservbyname(serv, "tcp")) == NULL)
** {
** printf("Unknown service %s. Check inet:db/services.\n",serv);
** return RETURN_ERROR;
** }
** sin.sin_port = servptr->s_port;
*/
sin.sin_port = htons(6666);
sin.sin_addr.s_addr = INADDR_ANY;
if(bind(s, (struct sockaddr *)&sin, len) < 0)
{
perror("bind");
exit(RETURN_ERROR);
}
/*
** Put socket into "listen" state (ready to accept connections).
*/
listen(s,5);
/*
** Accept connections from s and process them on ns.
*/
while(1)
{
if( (ns = accept(s,NULL,NULL)) >= 0)
handle_request(ns);
}
}
/*
** handle_request()
**
** Handles a request to send or receive a file over a given socket.
** Handling a request consists of the following:
** 1) receive the mode (send or receive -- MODE_OLDFILE or MODE_NEWFILE)
** 2) receive the filename
** 3) attempt to open the file
** 4) return "\0" for succesful open,
** specially formated informative error message otherwise
** 5) call function to send or receive the file
** 6) close the file we opened and the socket we were passed
*/
void handle_request(int s)
{
char buffer[LENGTH];
int mode; /* AmigaDOS file open mode (MODE_OLDFILE or MODE_NEWFILE) */
BPTR file; /* BCPL pointer to an AmigaDOS file handle */
/* Get the mode.
** Don't worry about making sure that we got what we wanted because we
** can't really screw anything up and we can't send an error message
** if our communcications are error-prone.
*/
recv(s, (char *)&mode, (int)sizeof(int), 0);
/* Get the filename which we'll read or write (depending on mode).
** (Assume that we get only null-terminated strings.)
*/
recv(s, buffer, LENGTH, 0);
/*
** Attempt to open file.
*/
if( !(file = Open(buffer, mode)) )
{
int len;
len = strlen(buffer);
strncat(buffer, "': ", LENGTH-4); /* 4 not 3 'cause of nul */
Fault(IoErr(), NULL, buffer+len+3, LENGTH-len-4);
send(s, buffer, strlen(buffer)+1, 0);
close(s);
return;
}
/*
** Indicate succesful opening of file.
*/
send(s, "\0", 1, 0);
/*
** Send or recieve the file.
*/
if(mode == MODE_OLDFILE)
send_file(s, file);
else
get_file(s, file);
Close(file);
close(s);
}
void send_file(int s, BPTR file)
{
char buffer[LENGTH];
long actualLength;
do
{
actualLength = Read(file, (void *)buffer, LENGTH);
if(actualLength < 0)
return; /* Error, but we have no way to report it. */
if(send(s, buffer, actualLength, 0) < 0)
return; /* Error, but we have no way to report it. */
}while(actualLength);
}
void get_file(int s, BPTR file)
{
char buffer[LENGTH];
int n;
do
{
n = recv(s, buffer, LENGTH, 0);
if(n < 0)
return; /* Error, but we have no way to report it. */
if(Write(file, (void *)buffer, n) < 0)
return; /* Error, but we have no way to report it. */
}while(n);
}