
/* Server.c 

   illustration of nonblocking sockets 

   companion to Writer.c

   compile, and name executables "server" and "writer"

   need two invocations of writer, say on sgi8.cs.ucdavis.edu and
   sgi9 .cs.ucdavis.edu, while server is running on, say, 
   sausage.engr.ucdavis.edu

   each invocation of writer keeps sending to server, which prints it 
   out locally, and also sends the message back, for verification 
   that server-to-writer half of the socket is working too

   usage:  server 

   see important note at the end of this file

*/

/* these are needed for socket calls */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/ioctl.h>

#define BUFSIZE 1000000
#define PORT 2723  /* server port number */

int ClntDescriptor[2],  /* socket descriptor to client */
    SrvrDescriptor,  /* socket descriptor for server */
    Port = PORT;

char InBuf[BUFSIZE];  /* messages from clients */

main(argc,argv)
   int argc;  char **argv;

{  struct sockaddr_in BindInfo;  int Flag = 1,NBytes,I;  

   SrvrDescriptor = socket(AF_INET,SOCK_STREAM,0);
   /* make the socket nonblocking */
   ioctl(SrvrDescriptor,FIONBIO,&Flag); 
   BindInfo.sin_family = AF_INET;
   BindInfo.sin_port = Port;
   BindInfo.sin_addr.s_addr = INADDR_ANY;
   bind(SrvrDescriptor,&BindInfo,sizeof(BindInfo));
   listen(SrvrDescriptor,5); 

   /* first set up the two client sockets */
   for (I = 0; I < 2; I++)  {
      /* wait until get a "call" from this socket; if the
         socket were blocking, then accept() would block
	 too, but for nonblocking sockets the behavior
	 of accept() is is nonblocking */
      while (1)  {
         ClntDescriptor[I] = accept(SrvrDescriptor,0,0);  
         if (ClntDescriptor[I] != -1) break;
      }
   }

   /* now do the experiment */
   for (I = 0; ; I = 1 - I)  {
      memset(InBuf,0,sizeof(InBuf));
      /* note that sockets produced as return values
         from accept() inherit the properties of the
	 socket in the first argument to the call,
	 so ClntDescriptor[I] is nonblocking, since
	 SrvrDescriptor was */ 
      /* poll socket I for bytes arrived; assume here that
         message is short enough to be received in one call
         to read() */
      NBytes = read(ClntDescriptor[I],InBuf,sizeof(InBuf));
      /* if bytes were there to be read then process them */
      if (NBytes != -1)  {
         printf("from socket %d:  %s\n",I,InBuf); 
         write(ClntDescriptor[I],InBuf,NBytes); 
      }
   }
   
}

/* if messages were longer, the call to read() would have to be in
   a loop, to make sure all bytes are received

   this is normally not a problem for calls to write(), but in the
   case of nonblocking sockets it is safest to put a write() in a
   loop too */



