/* Socket server demo * by OrangeTide (jmayo@mail.alliance.net) Dec 1996 */ #include #include #include #include #include /* needed for select() */ #include /* internet socket stuff */ #include /* network database stuff. (gethostbyname, etc) */ #define MAXHOSTNAME 80 /* I don't know what the posix keyword is for this */ #define PORT 50000 /* default port to use */ #undef DEBUGGING_INFO /* handy if you want to know what is * going on with the sockets. Just * provides a few extra tidbits that * aren't even that useful. I suppose * I should make this a cmdline option */ char *inet_ntoa(struct in_addr in); int atoi(const char *nptr); void print_hostent(const struct hostent *hp) { /* protos */ /* char *inet_ntoa(struct in_addr in); */ printf("%s (%s)\n", hp->h_name, inet_ntoa(*((struct in_addr *) (hp->h_addr)))); } int grab_port(unsigned short int portnum) { /* protos */ void print_hostent(const struct hostent *hp); unsigned short int htons(unsigned short int hostshort); void bzero(void *s, int n); /* vars */ struct hostent *hp; char myhost[MAXHOSTNAME + 1]; struct sockaddr_in sa; int s; /* the socket */ bzero(&sa, sizeof(struct sockaddr_in)); gethostname(myhost, MAXHOSTNAME); hp = gethostbyname(myhost); if (hp == NULL) { perror("socket build error: No Hostname"); return -1; } sa.sin_family = hp->h_addrtype; /* host address */ sa.sin_port = htons(portnum); /* port number */ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) /* build socket */ { perror("socket build error: Allocating socket"); return -1; /* error building socket */ } if (bind(s, (struct sockaddr*)&sa, sizeof sa) < 0) { perror("socket build error: Binding"); close(s); return -1; } listen(s, 3); /* max # in queue */ printf("Taking port %d on ", portnum); /* prints the local host */ print_hostent(hp); return s; /* return socket */ } int main(int argc, char *argv[]) { /* protos */ int grab_port(u_short portnum); /* vars */ int mysock[20 + 1]; /* max of twenty connection 0=bound socket, 1-20=normal */ fd_set sockrd; fd_set sockex; /* fd_set sockwr; */ fd_set completefd; /* struct timeval tv; */ int topfd; /* value of the top file descriptor */ int topsock = 0; /* top socket */ int portnum; int stay_connected = 1; /* keeps the while loop going */ /* code */ if (argc>1) portnum=atoi(argv[1]); else portnum=PORT; if ((mysock[0] = grab_port(portnum)) < 0) { perror("Cannot connect socket"); return -1; } topfd = mysock[0]; FD_ZERO(&completefd); FD_SET(mysock[0], &completefd); while (stay_connected) { sockrd = completefd; sockex = completefd; /* tv.tv_sec=1; tv.tv_usec=0; */ # ifdef DEBUGGING_INFO printf("select() start\n"); printf("topsock: %d\ntopfd: %d\n",topsock,topfd); # endif if (select(256/* topfd + 1 */, &sockrd, NULL, &sockex, NULL) > 0) { struct sockaddr_in myaddr; int myaddr_len; int i; /* index */ myaddr_len = sizeof(struct sockaddr_in); # ifdef DEBUGGING_INFO printf("select() done\n"); # endif /* some sort of code needs to be implementated to handle "exceptions" and * actually use &sockex, because I think that it has something to do with the * disconnection of a socket */ if (FD_ISSET(mysock[0], &sockrd)) { if ((mysock[++topsock] = accept(mysock[0], (struct sockaddr*)&myaddr, &myaddr_len)) < 0) perror("accept"); printf("%d!connection (%s)\n", topsock, inet_ntoa(myaddr.sin_addr)); FD_SET(mysock[topsock], &completefd); if (mysock[topsock]>topfd) topfd=mysock[topsock]; } /* else */ /* I have no idea why I even put this here! kludging working code, I guess */ for (i=1;i<=topsock;i++) { printf("%d!checking\n",i); if(FD_ISSET(mysock[i], &sockrd)) { char s[80]; int dataread; printf("%d!reading.\n",i); dataread=read(mysock[i],s,sizeof s); if (0==dataread) { printf("#%d!closed.\n",i); FD_CLR(mysock[i],&completefd); close(mysock[i]); mysock[i]=mysock[topsock--]; /* this hopefully swaps * top FD to the closed * fd and lowers the the * socket count */ } s[dataread]='\0'; printf("#%d:%s",i,s); } printf("*\n"); } } } /* we're done, let's close all the sockets */ while (topsock >= 0) if (close(mysock[topsock--]) != 0) perror("close"); return 0; } /* unsigned long ipaddr; if((ipaddr=inet_addr(myhost))==-1) hp=gethostbyname(myhost); else hp=gethostbyaddr((char *)&ipaddr, sizeof(struct in_addr), AF_INET); */