#include #include #include #include #include #include #include int open_listenfd(char *port); void echo(int connfd); #define LISTEN_MAX 10 /* Maximum clients that can queue up */ #define MAXLINE 512 int main(int argc, char **argv) { int listenfd, connfd, clientlen; char * port; union { struct sockaddr_in client4; struct sockaddr_in6 client6; } clientaddr; char hostname[NI_MAXHOST]; char hostaddr[NI_MAXHOST]; int error; port = argv[1]; /* the server listens on a port passed on the command line */ listenfd = open_listenfd(port); if (listenfd < 0) { if (listenfd == -1) (void) fprintf (stderr, "port %s: %s\n", port, strerror(errno)); exit(1); } while (1) { clientlen = sizeof clientaddr; connfd = accept(listenfd, (struct sockaddr *)&clientaddr, &clientlen); if (connfd == -1) { fprintf (stderr, "accept: %s\n", strerror(errno)); continue; } error = getnameinfo((struct sockaddr*)&clientaddr, clientlen, hostname, sizeof hostname, NULL, 0, 0); if (error != 0) { fprintf (stderr, "Couldn't get name info for client: %s\n", gai_strerror(error)); close(connfd); continue; } error = getnameinfo((struct sockaddr*)&clientaddr, clientlen, hostaddr, sizeof hostaddr, NULL, 0, NI_NUMERICHOST); if (error != 0) { fprintf (stderr, "Couldn't get numeric info for client %s: %s\n", hostname, gai_strerror(error)); close(connfd); continue; } printf("server connected to %s (%s)\n", hostname, hostaddr); echo(connfd); close(connfd); } } int open_listenfd(char *port) { int listenfd, optval=1; struct addrinfo hints; struct addrinfo *hostaddresses = NULL; int error; /* Find out the server's IP address and port */ memset(&hints, 0, sizeof hints); hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED | AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(NULL, port, &hints, &hostaddresses); if (error != 0) { freeaddrinfo(hostaddresses); fprintf (stderr, "port %s: %s\n", port, gai_strerror(error)); return -2; } /* Create a socket descriptor */ /* We take advantage of the fact that AF_* and PF_* are identical */ listenfd = socket(hostaddresses->ai_family, hostaddresses->ai_socktype, hostaddresses->ai_protocol); if (listenfd == -1) { freeaddrinfo(hostaddresses); return -1; } /* Eliminates "Address already in use" error from bind. */ if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof optval) == -1) return -1; /* Listenfd will be an endpoint for all requests to port on any IP address for this host */ if (bind(listenfd, hostaddresses->ai_addr, hostaddresses->ai_addrlen) == -1) { freeaddrinfo(hostaddresses); return -1; } /* Make it a listening socket ready to accept connection requests */ freeaddrinfo(hostaddresses); if (listen(listenfd, LISTEN_MAX) == -1) return -1; return listenfd; } void echo(int connfd) { size_t n; char buf[MAXLINE]; while((n = read(connfd, buf, sizeof buf)) > 0) { printf("server received %d bytes\n", n); write(connfd, buf, n); } }