/* NAME: TCPServer [Port number] SYNOPSIS: TCPServer DESCRIPTION: The program creates a TCP socket in the inet, listens for connections from TCPClients, accepts clients into private sockets, and forks an echo process to ``serve'' the cleint. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*gethostname*/ #define MAXHOSTNAME 80 #define BUF_SIZE 500 void reusePort(int sock); void EchoServe(int psd, struct sockaddr_storage from); int main(int argc, char *argv[]) { 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); for(;;){ from_addr_len = sizeof(from_addr); ns = accept(s, (struct sockaddr *) &from_addr, &from_addr_len); if (ns < 0) { perror("accept error"); exit(EXIT_FAILURE); } if ( fork() == 0) { close (s); EchoServe(ns, from_addr); } } } void EchoServe(int psd, struct sockaddr_storage from) { int f; char host[NI_MAXHOST], service[NI_MAXSERV]; char buf[BUF_SIZE]; int rc; f = getnameinfo((struct sockaddr *)&from, sizeof(from), host, NI_MAXHOST, service, NI_MAXSERV, NI_NUMERICSERV); if (f == 0) { printf("Serving %s:%s\n", host, service); } else{ fprintf(stderr, "getnameinfo: %s\n", gai_strerror(f)); exit(EXIT_FAILURE); } /* 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); printf("From TCP/Client: %s:%s\n", host, service); if (send(psd, buf, rc, 0) <0 ) perror("sending stream message"); } else { printf("TCP/Client: %s:%d\n", host, service); printf("Disconnected..\n"); close (psd); exit(0); } } } 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); } }