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 >
C/C++ Source or Header  |  1992-09-01  |  6KB  |  218 lines

  1. /*
  2. **  server.c
  3. **
  4. **  Written by Dale Larson, Software Engineer, Commodore-Amiga, Inc.
  5. **  Copyright 1991, Commodore-Amiga, Inc.
  6. **  Permission to use granted provided this notice remains intact.
  7. **
  8. **  This is a simple version of the ncopy server.  It processes only one
  9. **  request at a time.  This is adequate for a server which sees light or
  10. **  infrequent usage, but can lead to unacceptable delays for a server which
  11. **  sees heavy or even moderate trafic.  It also will cause problems if the
  12. **  user copies a file from a remote machine to the same remote machine
  13. **  (i.e.  ncopy sprite!ram:x sprite!work:y).
  14. **
  15. **  You should study and understand this server before you look at
  16. **  server2.c, which is significantly more complex.
  17. **
  18. **  This server has no provisions for exiting.
  19. **  A system requester will pop up if the server recieves a request to
  20. **  read/write to/from a device a non-existant device.
  21. */
  22.  
  23.  
  24. #include "ncopy.h"
  25.  
  26. struct Library *SockBase;
  27. #define MAXSOCKS 10
  28.  
  29. char vers[] = "\0$VER: server1 1.0 (25.02.91)";
  30.  
  31. void handle_request(int s);
  32. void send_file(int s, BPTR file);
  33. void get_file(int s, BPTR file);
  34.  
  35.  
  36. /*
  37. **  main()
  38. **
  39. **  Get a socket, bind a name to it, express a willingness to accept
  40. **  connections to it (listen) then wait to actually accept connections.
  41. **  Once a connection has been accepted, give the handler function the
  42. **  socket which accept() connected to a remote machine so that the handler
  43. **  function can chat with the remote machine.  When the handler returns,
  44. **  go back to waiting to accept connections.
  45. */
  46. main(int argc, char **argv)
  47. {
  48. struct sockaddr_in sin;    /*  socket address (internet) to establish  */
  49. int s, ns;        /*  socket and new socket  */
  50. size_t len = sizeof(sin);
  51.  
  52.     /*  Open Shared Socket library:
  53.     */
  54.         if(SockBase = OpenLibrary( "inet:libs/socket.library", 0L ))
  55.         {
  56.                 setup_sockets( MAXSOCKS, &errno );
  57.     }else
  58.     {
  59.         puts("Can't open socket.library.");
  60.         exit(RETURN_ERROR);
  61.     }
  62.  
  63.     /*
  64.     **  Initialize a socket.
  65.     */
  66.     if( (s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  67.     {
  68.         perror("socket");
  69.         exit(RETURN_ERROR);
  70.     }
  71.  
  72.     /*
  73.     **  Bind name to socket.
  74.     **  Since we got sin off the stack, it could contain anything, and so
  75.     **  we zero it before initializing it.
  76.     */
  77.     bzero(&sin, (int)len);
  78.     sin.sin_family = AF_INET;
  79.     /*
  80.     **  While prototyping a program, pick an unused port number above
  81.     **  1024 like I did here.  For a real program, assign a name and a
  82.     **  port number above 1024 and stick it in inet:db/servers on all
  83.     **  machines which will use the application.  That way the user can
  84.     **  reconfigure port numbers used by new applications if necessary.
  85.     **  You can modify the server to get the port number from the
  86.     **  database by using code like this (instead of "sin.sin_port=
  87.     **  htons(6666)" below):
  88.     **
  89.     **  struct servent *servptr;
  90.     **  char serv[] = "servicename";
  91.     **
  92.     **  if( (servptr = getservbyname(serv, "tcp")) == NULL)
  93.     **  {
  94.     **      printf("Unknown service %s.  Check inet:db/services.\n",serv);
  95.     **    return RETURN_ERROR;
  96.     **  }
  97.     **  sin.sin_port = servptr->s_port;
  98.     */
  99.     sin.sin_port = htons(6666);
  100.     sin.sin_addr.s_addr = INADDR_ANY;
  101.     if(bind(s, (struct sockaddr *)&sin, len) < 0)
  102.     {
  103.         perror("bind");
  104.         exit(RETURN_ERROR);
  105.     }
  106.  
  107.     /*
  108.     **  Put socket into "listen" state (ready to accept connections).
  109.     */
  110.     listen(s,5);
  111.  
  112.     /*
  113.     **  Accept connections from s and process them on ns.
  114.     */
  115.     while(1)
  116.     {
  117.         if( (ns = accept(s,NULL,NULL)) >= 0)
  118.             handle_request(ns);
  119.     }
  120. }
  121.  
  122.  
  123. /*
  124. **  handle_request()
  125. **
  126. **  Handles a request to send or receive a file over a given socket.
  127. **  Handling a request consists of the following:
  128. **      1)  receive the mode (send or receive -- MODE_OLDFILE or MODE_NEWFILE)
  129. **    2)  receive the filename
  130. **    3)  attempt to open the file
  131. **    4)  return "\0" for succesful open,
  132. **        specially formated informative error message otherwise
  133. **    5)  call function to send or receive the file
  134. **    6)  close the file we opened and the socket we were passed
  135. */
  136. void handle_request(int s)
  137. {
  138. char buffer[LENGTH];
  139. int mode;    /*  AmigaDOS file open mode (MODE_OLDFILE or MODE_NEWFILE)  */
  140. BPTR file;    /*  BCPL pointer to an AmigaDOS file handle  */
  141.  
  142.  
  143.     /*  Get the mode.
  144.     **  Don't worry about making sure that we got what we wanted because we
  145.     **  can't really screw anything up and we can't send an error message
  146.     **  if our communcications are error-prone.
  147.     */
  148.     recv(s, (char *)&mode, (int)sizeof(int), 0);
  149.  
  150.     /*  Get the filename which we'll read or write (depending on mode).
  151.     **  (Assume that we get only null-terminated strings.)
  152.     */
  153.     recv(s, buffer, LENGTH, 0);
  154.  
  155.     /*
  156.     **  Attempt to open file.
  157.     */
  158.     if( !(file = Open(buffer, mode)) )
  159.     {
  160.     int len;
  161.  
  162.         len = strlen(buffer);
  163.         strncat(buffer, "': ", LENGTH-4);  /*  4 not 3 'cause of nul  */
  164.         Fault(IoErr(), NULL, buffer+len+3, LENGTH-len-4);
  165.         send(s, buffer, strlen(buffer)+1, 0);
  166.         close(s);
  167.         return;
  168.     }
  169.  
  170.     /*
  171.     **  Indicate succesful opening of file.
  172.     */
  173.     send(s, "\0", 1, 0);
  174.  
  175.     /*
  176.     **  Send or recieve the file.
  177.     */
  178.     if(mode == MODE_OLDFILE)
  179.         send_file(s, file);
  180.     else
  181.         get_file(s, file);
  182.  
  183.     Close(file);
  184.     close(s);
  185. }
  186.  
  187.  
  188. void send_file(int s, BPTR file)
  189. {
  190. char    buffer[LENGTH];
  191. long    actualLength;
  192.  
  193.     do
  194.     {
  195.         actualLength = Read(file, (void *)buffer, LENGTH);
  196.             if(actualLength < 0)
  197.             return;  /*  Error, but we have no way to report it.  */
  198.         if(send(s, buffer, actualLength, 0) < 0)
  199.             return;  /*  Error, but we have no way to report it.  */
  200.     }while(actualLength);
  201. }
  202.  
  203.  
  204. void get_file(int s, BPTR file)
  205. {
  206. char    buffer[LENGTH];
  207. int     n;
  208.  
  209.     do
  210.     {
  211.         n = recv(s, buffer, LENGTH, 0);
  212.         if(n < 0)
  213.             return;  /*  Error, but we have no way to report it.  */
  214.         if(Write(file, (void *)buffer, n) < 0)
  215.             return;  /*  Error, but we have no way to report it.  */
  216.     }while(n);
  217. }
  218.