home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / ip / sized_io.shar.Z / sized_io.shar / stream.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-28  |  4.4 KB  |  173 lines

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <sys/time.h>
  5. #include <netinet/in.h>
  6. #include <netdb.h>
  7. #include <errno.h>
  8. #include "inet.h"
  9.  
  10. #define MAXHOSTNAMELENGTH 255
  11. static char hostname[MAXHOSTNAMELENGTH];
  12.  
  13. extern errno;
  14. static int maxfds;
  15. static struct timeval zerotime;
  16.  
  17. #define server (role == SERVER)
  18. #define client (role == CLIENT)
  19.  
  20. int        /* returns a socket, or -1 for failure */
  21. initport(porttype,port_name,port_number,role,sockettype,host_in)
  22. int porttype;
  23. char *port_name;
  24. u_short port_number;
  25. int role;
  26. int sockettype;
  27. char *host_in;            /* host to provide service */
  28. {
  29.     int s;        /* the socket */
  30.     struct sockaddr_in sin;
  31.     struct hostent *h;
  32.     struct servent *sp;    /* used by getservbyname */
  33.  
  34.     maxfds = getdtablesize();    /* for future reference */
  35.     /* prevent narrow fd_set binaries from blowing up with with */
  36.     /* large getdtablesize() */
  37. #ifdef FD_SET_SIZE
  38.     maxfds = ((FD_SET_SIZE > maxfds)?maxfds:FD_SET_SIZE);
  39. #endif
  40.  
  41.     zerotime.tv_sec = zerotime.tv_usec = 0L;
  42.  
  43.     if (client) {
  44.     if (host_in && strcmp(host_in,"")) strcpy(hostname,host_in);
  45.     else {
  46.         if (gethostname(hostname,MAXHOSTNAMELENGTH)) {
  47.         perror("initport: gethostname");
  48.         return(-1);
  49.         }
  50.     }
  51.  
  52.     if (!(h = gethostbyname(hostname))) {
  53.         fprintf(stderr,"initport: gethostbyname(%s): failed\n",hostname);
  54.         return(-1);
  55.     }
  56.     }
  57.  
  58.     if (porttype == PORT_TYPE_NAME) {
  59.     if (!(sp = getservbyname(port_name,(char *)0))) {
  60.             fprintf(stderr,"initport: getservbyname(%s): failed\n",port_name);
  61.             exit(-1);
  62.     }
  63.     }
  64.  
  65.     if (-1 == (s = socket(AF_INET,sockettype,0))) {
  66.     perror("initport: socket");
  67.     return(-1);
  68.     }
  69.  
  70.     sin.sin_family = AF_INET;
  71.     sin.sin_addr.s_addr = (server?INADDR_ANY:*(u_long *) h->h_addr);
  72.     sin.sin_port = (porttype == PORT_TYPE_NAME?sp->s_port:htons(port_number));
  73.  
  74.     if (client) {
  75.     if (connect(s,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))) {
  76.         perror("initport: connect");
  77.         return(-1);
  78.     }
  79.     } else {
  80.     /* bind the socket */
  81.     /* following line allows reuse immediately after previous user */
  82.     /* otherwise you have to wait a minute or two */
  83.     setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)0,0);
  84.     if (-1 == (bind(s,(struct sockaddr *)&sin,sizeof(sin)))) {
  85.         perror("initport: bind");
  86.         return(-1);
  87.     }
  88.     if (listen(s,1)) {
  89.         perror("initport: listen");
  90.         return(-1);
  91.     }
  92.     }
  93.     return(s);
  94. }
  95.  
  96. select_server_stream(connection_socket,readers)
  97. int connection_socket;
  98. fd_set *readers;    /* file descriptors of client sockets */
  99. {
  100.     struct sockaddr_in from;
  101.     int fromlen;
  102.     static int fd;    /* next file descriptor to look at */
  103.     int c;
  104.     fd_set readfds;
  105.     int user;
  106.  
  107.     /* how do you get sockets to block?  there is some hint (recv(2)) */
  108.     /* in the manual that you can but I can't find the reference! */
  109.  
  110.     /* select does not like bogus file descriptors, so keep track of */
  111.     /* them by hand */
  112.     FD_SET(connection_socket,readers);
  113.  
  114. restart:
  115.     do {
  116.     /* save readers because select wipes them out */
  117.     readfds = *readers;
  118.     c = select(maxfds,&readfds,(fd_set *)0,(fd_set *)0,
  119.                         (struct timeval *)0);
  120.     if (c == -1) {
  121.         if (errno == EBADF) {
  122.         int i;
  123.         /* someone augered in, lets forget about'm */
  124.         for (i=0;i<maxfds;i++) {
  125.             fd_set suspect;
  126.             FD_ZERO(&suspect);
  127.             if (FD_ISSET(i,readers)) {
  128.             /* use a temporary for the suspect because select() */
  129.             /* requires an address */
  130.             FD_SET(i,&suspect);
  131.             if (-1 == select(maxfds,&suspect,
  132.                         (fd_set *)0,(fd_set *)0,
  133.                         &zerotime)) {
  134.                 /* found a reader who closed his socket */
  135.                 /* so get rid of him */
  136.                 FD_CLR(i,readers);
  137.             }
  138.             FD_CLR(i,&suspect);
  139.             }
  140.         }
  141.         } else {
  142.         /* lets hope it was a recoverable interrupt and try again */
  143.         perror("select_server_stream: select");
  144.         exit(-1);
  145.         }
  146.     }
  147.     } while (c == -1);
  148.     /* given the set of ready file descriptors pick one out that is ready */
  149.     /* start from where we left off, so as to give everyone service */
  150.     while (TRUE) {
  151.     fd = (1+fd)%maxfds;
  152.     if (FD_ISSET(fd,&readfds)) break;
  153.     }
  154.  
  155.     if (fd == connection_socket) {    /* check for new connections */
  156.     fromlen = sizeof(from);
  157.     user = accept(connection_socket,(struct sockaddr *)&from,&fromlen);
  158.     FD_SET(user,readers);
  159.     goto restart;
  160.     }
  161.  
  162.     return(fd);
  163. }
  164.  
  165. print_address(x)
  166. struct sockaddr_in *x;
  167. {
  168.     printf("x->sin_family = %d\n",(int)x->sin_family);
  169.     printf("x->sin_port = %d\n",(int)x->sin_port);
  170.     printf("x->sin_addr.s_addr = %d\n",(int)x->sin_port);
  171.     printf("x->sin_zero[0] = %c\n",x->sin_zero[0]);
  172. }
  173.