/* 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; struct linger l; 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(); } l.l_onoff = 1; l.l_linger = 0; if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) == -1) { printf("setsockopt: %d\n", errno); abort(); } bzero(&l, sizeof(l)); sz = sizeof(l); if (getsockopt(fd, SOL_SOCKET, SO_LINGER, &l, &sz) == -1) { printf("getsockopt: %d\n", errno); abort(); } printf("listener l_onoff = %d, l_linger = %d\n", l.l_onoff, l.l_linger); 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); bzero(&l, sizeof(l)); if (getsockopt(clfd, SOL_SOCKET, SO_LINGER, &l, &sz) == -1) { printf("getsockopt: %d\n", errno); abort(); } printf("client l_onoff = %d, l_linger = %d\n", l.l_onoff, l.l_linger); 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); }