/* * Concurrent Echo Servers on port 60000 for Transfer Control Protocol * */

#ifndef unix #include <winsock2.h> /* also include Ws2_32.lib library in linking options */ #else #define closesocket close #define SOCKET int #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <unistd.h> /* also include xnet library for linking; on command line add: -lxnet */ #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #define PROTOPORT 60000 /* default protocol port number */ #define QLEN 5 /* size of request queue */ int OneTCPEcho(SOCKET s); int main(int argc, char *argv[]) { struct protoent *ptrp; /* pointer to a protocol table entry */ struct sockaddr_in sad; /* structure to hold server's address */ struct sockaddr_in cad; /* structure to hold client's address */ SOCKET sd; /* server socket descriptor */ int port; /* protocol port number */ int alen; /* length of address */ fd_set rfds; /* read file descriptor set */ fd_set afds; /* active file descriptor set */ #ifdef WIN32 WSADATA wsaData; if(WSAStartup(0x0101, &wsaData)!=0) { fprintf(stderr, "Windows Socket Init failed: %d\n", GetLastError()); exit(1); } #endif memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */ if (argc > 1) { /* if argument specified */ port = atoi(argv[1]); /* convert argument to binary */ } else { port = PROTOPORT; /* use default port number */ } if (port <= 0) /* test for illegal value */ { /* print error message and exit */ fprintf(stderr,"bad port number %s\n",argv[1]); exit(1); } sad.sin_port = htons((u_short)port); /* set server port number */ sad.sin_family = AF_INET; /* set family to Internet */ sad.sin_addr.s_addr = INADDR_ANY; /* set the local IP address */ /* Map TCP transport protocol name to protocol number */ ptrp = getprotobyname("tcp"); if (ptrp == 0) { fprintf(stderr, "cannot map \"tcp\" to protocol number"); exit(1); } /* Create a socket */ sd = socket(PF_INET, SOCK_STREAM, ptrp->p_proto); if (sd < 0) { fprintf(stderr, "socket creation failed\n"); exit(1); } /* In case the server crashes allow to reuse the port number ASAP without socket timeout */ { const int on = 1; if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) < 0) { fprintf(stderr, "Warining: in case of failure the port number cannot be reused immediately\n"); } } /* Bind a local address to the socket */ if (bind(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) { fprintf(stderr,"bind failed\n"); exit(1); } /* Specify size of request queue */ if (listen(sd, QLEN) < 0) { fprintf(stderr,"listen failed\n"); exit(1); } FD_ZERO(&afds); FD_SET(sd, &afds); while (1) { unsigned int fdndx; int status; memcpy(&rfds, &afds, sizeof(rfds)); status=select(FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0 ); if (status<0) { fprintf(stderr,"select failed\n"); exit(1); } if (FD_ISSET(sd, &rfds)) { SOCKET sd2; alen = sizeof(cad); sd2 = accept(sd, (struct sockaddr *)&cad, &alen); if (sd2<0) { fprintf(stderr,"accept failed\n"); exit(1); } FD_SET(sd2, &afds); } #ifndef unix for (fdndx=0; fdndx<rfds.fd_count; ++fdndx) { SOCKET sd3=rfds.fd_array[fdndx]; #else for (SOCKET sd3=0; sd3<FD_SETSIZE; ++sd3) { #endif if (sd3!=sd && FD_ISSET(sd3, &rfds)) if (OneTCPEcho(sd3)==0) { (void) closesocket(sd3); FD_CLR(sd3, &afds); } } } closesocket(sd); #ifdef WIN32 WSACleanup(); #endif return(0); } int OneTCPEcho(SOCKET s) { char buf[65536]; /* buffer for string the echoing */ int n; /* number of characters received */ int m; /* number of characters sent back */ n = recv(s, buf, sizeof(buf), 0); if (n < 0) { fprintf(stderr,"Error in receiving\n"); } else if (n==0) { /* Remote closed the connection */ } else if (n > 0) { m = send(s,buf,n,0); if(m<0){ fprintf(stderr,"Error in sending\n"); } } return(n); }