/* NAME: TCPServer SYNOPSIS: TCPServer [Port_number] DESCRIPTION: The program creates a TCP socket in the inet listen for connections from TCPClients, accept clients into private sockets. It uses select to attend clients' requests as they come. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAXHOSTNAME 80 #define BUF_SIZE 500 void reusePort(int sock); int EchoServe(int psd); int main(int argc, char *argv[]) { fd_set readfds, readfdsCopy; int n,i; int sockList[64], lastSock=0; struct addrinfo hints, *result, *rp; struct addrinfo hints_local, *result_local; int sfd, s, ns; struct sockaddr_storage from_addr; socklen_t from_addr_len; ssize_t nread; char buffer[BUF_SIZE]; char ThisHost[80]; if (argc != 2) { fprintf(stderr, "Usage: %s port\n", argv[0]); exit(EXIT_FAILURE); } gethostname(ThisHost, MAXHOSTNAME); /*Obtain address(es) matching localhost/localport*/ memset(&hints_local, 0, sizeof(hints_local)); hints_local.ai_family = AF_INET; //IPv4 hints_local.ai_socktype = SOCK_STREAM; //TCP hints_local.ai_flags = AI_PASSIVE; if (getaddrinfo(ThisHost, argv[1], &hints_local, &result_local) != 0) { fprintf(stderr, "getaddrinfo error\n"); exit(EXIT_FAILURE); } printf("----EchoServer/TCP running at host NAME: %s\n", ThisHost); printf("(EchoServer/TCP INET ADDRESS is: %s )\n", inet_ntoa(((struct sockaddr_in*)result_local->ai_addr)->sin_addr)); printf("Server Port is: %s \n", argv[1]); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; //IPv4 hints.ai_socktype = SOCK_STREAM; //TCP hints.ai_flags = AI_PASSIVE; //For wildcard IP address if ((getaddrinfo(NULL, argv[1], &hints, &result)) != 0) { fprintf(stderr, "getaddrinfo error\n"); exit(EXIT_FAILURE); } /* getaddrinfo() returns a list of address structures. Try each address until we successfully bind. If socket (or bind) fails, we (close the socket and) try the next address. */ for (rp = result; rp != NULL; rp = rp -> ai_next) { s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); reusePort(s); if (s == -1) { continue; } if (bind(s, rp -> ai_addr, rp -> ai_addrlen) == 0) { break; //Success } close(s); } freeaddrinfo(result); //No longer needed if (rp == NULL) { fprintf(stderr, "Could not bind\n"); exit(EXIT_FAILURE); } listen(s,4); from_addr_len = sizeof(from_addr); FD_ZERO(&readfdsCopy); FD_SET(s,&readfdsCopy); for(;;){ memcpy(&readfds, &readfdsCopy, sizeof(fd_set)); n = select(FD_SETSIZE, &readfds, (fd_set *) 0, (fd_set *) 0, NULL); if (n > 0) { if (FD_ISSET(s, &readfds)) { printf("Accepting a new connection...\n"); sockList[lastSock++] = accept(s, (struct sockaddr *) &from_addr, &from_addr_len); FD_SET(sockList[lastSock-1], &readfdsCopy); } for (i=0; i < lastSock; i++) { if (FD_ISSET(sockList[i], &readfds)) if (EchoServe(sockList[i]) < 0) { FD_CLR(sockList[i], &readfdsCopy); close (sockList[i]); sockList[i] = sockList[--lastSock]; i--; printf("Number of current clients: %d\n", lastSock); } } } } } int EchoServe(int psd) { char buf[512]; int rc; /* get data from clients and send it back */ for(;;){ printf("\n...server is waiting...\n"); if( (rc=read(psd, buf, sizeof(buf))) < 0) perror("receiving stream message"); if (rc > 0){ buf[rc]='\0'; printf("Received: %s\n", buf); if (send(psd, buf, rc, 0) <0 ) perror("sending stream message"); return(1); } else { printf("Disconnected..\n"); return(-1); } } } 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); } }