/* NAME: UDP.ECHO.SERVER SYNOPSIS: UDPServer port_number DESCRIPTION: The program creates a datagram socket in the inet domain, then receives messsages from client process and echos it back to it. */ #include #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 main(int argc, char * argv[]) { struct addrinfo hints, *result, *rp; struct addrinfo hints_local, *result_local; int sfd, s; struct sockaddr_storage peer_addr; socklen_t peer_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_DGRAM; //UDP 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 running at host NAME: %s\n", ThisHost); printf("(EchoServer 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_DGRAM; //UDP 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) { sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sfd == -1) continue; reusePort(sfd); if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0) break; /* Success */ close(sfd); } freeaddrinfo(result); /* No longer needed */ if (rp == NULL) { /* No address succeeded */ fprintf(stderr, "Could not bind\n"); exit(EXIT_FAILURE); } /* Read datagrams and echo them back to sender. */ while (1) { peer_addr_len = sizeof(peer_addr); printf("\n...server is waiting...\n"); nread = recvfrom(sfd, buffer, BUF_SIZE, 0, (struct sockaddr *)&peer_addr, &peer_addr_len); buffer[nread]='\0'; if (nread == 1) { continue; //Ignore failed request } char host[NI_MAXHOST], service[NI_MAXSERV]; s = getnameinfo((struct sockaddr *)&peer_addr, peer_addr_len, host, NI_MAXHOST, service, NI_MAXSERV, NI_NUMERICSERV); if (s == 0) { printf("Received: %s from %s:%s\n", buffer, host, service); } else fprintf(stderr, "getnameinfo: %s\n", gai_strerror(s)); if (sendto(sfd, buffer, nread, 0, (struct sockaddr *)&peer_addr, peer_addr_len) != nread) { fprintf(stderr, "Error sending response\n"); } } } 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); } }