#include #include #include #include #include #include #include #include #include static const int backlog = 10; static void handle_client(int fd); int main(int argc, char **argv) { struct addrinfo *ai; struct addrinfo hints = {.ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_flags = AI_PASSIVE}; int res, fd; if (argc != 2) errx(1, "usage: %s port", argv[0]); res = getaddrinfo(NULL, argv[1], &hints, &ai); if (res) errx(EXIT_FAILURE, "getaddrinfo: %s", gai_strerror(res)); fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (fd < 0) err(EXIT_FAILURE, "socket"); res = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &res, sizeof(res))) err(EXIT_FAILURE, "setsockopt"); if (bind(fd, ai->ai_addr, ai->ai_addrlen)) err(EXIT_FAILURE, "bind"); if (listen(fd, backlog)) err(EXIT_FAILURE, "listen"); for (;;) { struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); char ip[128] = {0}; int newfd; /* accept(fd, NULL, NULL) */ newfd = accept(fd, (struct sockaddr *)&addr, &addrlen); if (newfd < 0) err(EXIT_FAILURE, "accept"); getnameinfo((struct sockaddr *)&addr, addrlen, ip, sizeof(ip), NULL, 0, NI_NUMERICHOST); fprintf(stderr, "new connection from %s\n", ip); handle_client(newfd); fprintf(stderr, "close connection\n"); close(newfd); } close(fd); freeaddrinfo(ai); } static void handle_client(int fd) { char buf[64]; for (;;) { size_t count = read(fd, buf, sizeof(buf)), offset = 0; if (count < 0) { if (errno == EAGAIN || errno == EINTR) continue; err(EXIT_FAILURE, "read"); } if (count == 0) break; while (offset < count) { ssize_t res = write(fd, buf + offset, count - offset); if (res < 0) { if (errno == EAGAIN || errno == EINTR) continue; err(EXIT_FAILURE, "write"); } offset += res; } } }