/* * NAME: TCPServer SYNOPSIS: TCPServer [port] * * DESCRIPTION: The program creates a TCP socket in the inet listen for * connections from TCPClients, accept clients into private sockets, and use * select to echo ``serve'' the client. If [port] is not specified, the * program uses any available port. * */ #include "def" #define MAXHOSTNAME 80 #define MAXCLIENTS 10 void reusePort(int sock); int client[MAXCLIENTS]; fd_set readset, allset; int i; main(argc, argv) int argc; char *argv[]; { int sd, psd; struct sockaddr_in server; struct hostent *hp, *gethostbyname(); struct servent *sp; struct sockaddr_in from[MAXCLIENTS]; struct sockaddr_in fromi; int fromlen; int length; char ThisHost[80]; int pn; int childpid; int nb; struct timeval wait; int TIMEOUT = 0; sp = getservbyname("echo", "tcp"); /* get TCPServer1 Host information, NAME and INET ADDRESS */ gethostname(ThisHost, MAXHOSTNAME); /* OR strcpy(ThisHost,"localhost"); */ printf("----TCP/Server running at host NAME: %s\n", ThisHost); if ((hp = gethostbyname(ThisHost)) == NULL) { fprintf(stderr, "Can't find host %s\n", argv[1]); exit(-1); } bcopy(hp->h_addr, &(server.sin_addr), hp->h_length); printf(" (TCP/Server INET ADDRESS is: %s )\n", inet_ntoa(server.sin_addr)); /** Construct name of socket */ server.sin_family = AF_INET; /* OR server.sin_family = hp->h_addrtype; */ server.sin_addr.s_addr = htonl(INADDR_ANY); if (argc == 1) server.sin_port = htons(0); else { pn = htons(atoi(argv[1])); server.sin_port = pn; } /* OR server.sin_port = sp->s_port; */ /** Create socket on which to send and receive */ sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); /* OR sd = socket (hp->h_addrtype,SOCK_STREAM,0); */ if (sd < 0) { perror("opening stream socket"); exit(-1); } /** this allow the server to re-start quickly instead of fully wait for TIME_WAIT which can be as large as 2 minutes */ reusePort(sd); if (bind(sd, (SA *) & server, sizeof(server)) < 0) { close(sd); perror("binding name to stream socket"); exit(-1); } /** get port information and prints it out */ length = sizeof(server); if (getsockname(sd, (SA *) & server, &length)) { perror("getting socket name"); exit(0); } printf("Server Port is: %d\n", ntohs(server.sin_port)); /** accept TCP connections from clients and use select to serve each */ listen(sd, 4); fromlen = sizeof(fromi); for (i = 0; i < MAXCLIENTS; i++) client[i] = -1; /* -1 indicates available entry */ FD_ZERO(&allset); FD_SET(sd, &allset); wait.tv_sec = 1; wait.tv_usec = 0; for (;;) { readset = allset; /* structure assignment */ if (TIMEOUT) nb = select(MAXCLIENTS, &readset, NULL, NULL, NULL); else nb = select(MAXCLIENTS, &readset, NULL, NULL, &wait); if (nb == 0){ printf("TIME OUT\n"); TIMEOUT = 1; } if (FD_ISSET(sd, &readset)) { /* new client connection */ psd = accept(sd, (SA *) & fromi, &fromlen); for (i = 0; i < MAXCLIENTS; i++) if (client[i] < 0) { client[i] = psd; /* save descriptor */ from[i]=fromi; FD_SET(psd, &allset); /* add new descriptor to set */ break; } if (i == MAXCLIENTS) { printf("too many clients"); exit(0); } } for (i = 0; i <= MAXCLIENTS; i++) { /* check all clients for * data */ if ((psd = client[i]) < 0) continue; if (FD_ISSET(psd, &readset)) EchoServe(psd, from[i], i); } } } EchoServe(psd, from, i) int psd; struct sockaddr_in from; int i; { char buf[512]; int rc; struct hostent *hp, *gethostbyname(); printf("Serving %s:%d\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port)); if ((hp = gethostbyaddr((char *) &from.sin_addr.s_addr, sizeof(from.sin_addr.s_addr), AF_INET)) == NULL) fprintf(stderr, "Can't find host %s\n", inet_ntoa(from.sin_addr)); else printf("(Name is : %s)\n", hp->h_name); /** get data from clients and send it back */ printf("\n...server is waiting...\n"); if ((rc = recv(psd, buf, sizeof(buf), 0)) < 0) { perror("receiving stream message"); } if (rc > 0) { buf[rc] = NULL; printf("Received: %s\n", buf); printf("From TCP/Client: %s:%d\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port)); printf("(Name is : %s)\n", hp->h_name); if (send(psd, buf, rc, 0) < 0) perror("sending stream message"); } else { printf("TCP/Client: %s:%d\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port)); printf("(Name is : %s)\n", hp->h_name); printf("Disconnected..\n"); FD_CLR(psd, &allset); client[i] = -1; close(psd); } } void reusePort(int s) { int one = 1; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)) == -1) { printf("error in setsockopt,SO_REUSEPORT \n"); exit(-1); } }