/* cc -pthread tcpr.c */ #include #include #include #include #include #include #include #include #include #include #include #include #define PORT 8993 #define SPORT __XSTRING(PORT) static int listening; static char msg[] = { 1, 2, 3, 4 }; static void filladdr(struct addrinfo *hints, struct addrinfo **res) { int error; memset(hints, 0, sizeof(*hints)); hints->ai_family = AF_INET; hints->ai_socktype = SOCK_STREAM; hints->ai_flags = AI_NUMERICHOST; if ((error = getaddrinfo("127.0.0.1", SPORT, hints, res)) != 0) { printf("getaddrinfo: %s\n", gai_strerror(error)); abort(); } } static void * server_thr(void *data) { struct addrinfo hints, *res; struct sockaddr_in addr; socklen_t sz; int clfd, error, fd, reuse; filladdr(&hints, &res); fd = socket(PF_INET, SOCK_STREAM, 0); if (fd == -1) { printf("socket: %d\n", errno); abort(); } reuse = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse)); setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &reuse, sizeof(reuse)); if (bind(fd, res->ai_addr, res->ai_addrlen) == -1) { printf("bind: %d\n", errno); abort(); } if (listen(fd, SOMAXCONN) == -1) { printf("listen: %d\n", errno); abort(); } sz = sizeof(addr); atomic_store_int(&listening, 1); clfd = accept(fd, (struct sockaddr *)&addr, &sz); printf("got client\n"); for (;;) { error = write(clfd, msg, sizeof(msg)); if (error == 0) { printf("connection closed (good!)\n"); break; } else if (error < 0) { if (errno == EPIPE) printf("pipe gone (good!)\n"); else printf("write fail (bad!): %d\n", errno); break; } } close(clfd); close(fd); return (NULL); } int main(int argc, char *argv[]) { void *ret; pthread_t thr; struct addrinfo hints, *res; int error, fd; pthread_create(&thr, NULL, server_thr, NULL); filladdr(&hints, &res); fd = socket(PF_INET, SOCK_STREAM, 0); if (fd == -1) { printf("client socket: %d\n", errno); abort(); } printf("waiting for server\n"); while (atomic_load_int(&listening) != 1) usleep(1000); printf("attempting to connect\n"); for (;;) { if (connect(fd, res->ai_addr, res->ai_addrlen) == 0) break; if (errno != ECONNREFUSED) { printf("connect: %d\n", errno); abort(); } usleep(1000); } printf("connected, closing\n"); shutdown(fd, SHUT_RDWR); close(fd); printf("waiting\n"); pthread_join(thr, &ret); return (0); }