#include #include #include #include #include #include #include #include #include #include #include #ifndef NI_MAXHOST #define NI_MAXHOST 1025 #endif static void die(const char *msg) { printf("%s\n", msg); exit(1); } int main(void) { int err; struct addrinfo *res, hints = { .ai_family = AF_INET6, .ai_socktype = SOCK_STREAM, .ai_flags = AI_PASSIVE }; /* set up the server socket (listen on ::) */ err = getaddrinfo(NULL, "8080", &hints, &res); if (err) die(gai_strerror(err)); int sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sock < 0) die(strerror(errno)); err = bind(sock, res->ai_addr, res->ai_addrlen); if (err) die(strerror(errno)); err = listen(sock, 10); if (err) die(strerror(errno)); freeaddrinfo(res); err = fcntl(sock, F_SETFD, FD_CLOEXEC); if (err) die(strerror(errno)); pid_t child = fork(); if (child < 0) die(strerror(errno)); if (child == 0) { /* the child connects to the server socket and starts writing data to it */ hints.ai_flags = 0; err = getaddrinfo("fe80::216:d3ff:fece:57d9%eth0", "8080", &hints, &res); if (err) die(gai_strerror(err)); int fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (fd < 0) die(strerror(errno)); err = connect(fd, res->ai_addr, res->ai_addrlen); if (err) die(strerror(errno)); freeaddrinfo(res); for (;;) { const char buffer[4*1024]; err = write(fd, buffer, sizeof(buffer)); if (err < 0) die(strerror(errno)); printf("child: wrote %d bytes\n", err); } } else { /* the server accepts the connection and starts reading from it */ struct sockaddr_in6 sin6; socklen_t socklen = sizeof(sin6); int clientfd = accept(sock, (struct sockaddr *) &sin6, &socklen); if (clientfd < 0) die(strerror(errno)); char hostname[NI_MAXHOST] = ""; err = getnameinfo((struct sockaddr *)&sin6, socklen, hostname, NI_MAXHOST, NULL, 0, 0); printf("hostname: %s\n", hostname); fd_set readfds; FD_ZERO(&readfds); FD_SET(clientfd, &readfds); for (;;) { err = select(clientfd + 1, &readfds, NULL, NULL, NULL); if (err < 0) die(strerror(errno)); char buffer[4*1024]; err = read(clientfd, buffer, sizeof(buffer)); printf("parent: read %d bytes\n", err); FD_SET(clientfd, &readfds); } } return 0; }