Okay I was able to do it without fork. This one been tested on Arch Linux and Ubuntu. It's simpler I think and also won't give the bind error. It's below and attached.
William Morriss #include <arpa/inet.h> #include <assert.h> #include <errno.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> const int PORTNUM = 2423; const int BACKLOG = 16; int in_socketfd; void handle(int interrupt) { sched_yield(); close(in_socketfd); exit(0); } void server() { // on SIGINT, exit cleanly struct sigaction term_act; term_act.sa_handler = handle; sigemptyset(&term_act.sa_mask); term_act.sa_flags = 0; if (sigaction(SIGINT, &term_act, NULL)) { perror("sigaction"); exit(errno); } in_socketfd = socket(AF_INET, SOCK_STREAM, 0); if (in_socketfd == -1) { perror("socket"); exit(errno); } struct sockaddr_in in_addr; memset(&in_addr,0,sizeof(in_addr)); in_addr.sin_family = AF_INET; in_addr.sin_addr.s_addr = htonl(INADDR_ANY); in_addr.sin_port = htons(PORTNUM); if (bind(in_socketfd, (struct sockaddr*)&in_addr, sizeof(struct sockaddr_in))) { perror("bind"); exit(errno); }; if (listen(in_socketfd,BACKLOG)) { perror("listen"); exit(errno); } while (1) { struct sockaddr_in dest; socklen_t dest_size = sizeof(struct sockaddr_in); int socketfd = accept(in_socketfd, (struct sockaddr*) &dest, &dest_size); if (socketfd == -1) { perror("accept"); exit(errno); } char placeholder[15]; assert(recv(socketfd, placeholder, 15, 0) == 0); close(socketfd); } } int client() { int i; for (i = 0; i < 50000; i++) { int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { perror("socket"); return errno; } struct sockaddr_in dest; memset(&dest,0,sizeof(dest)); dest.sin_family = AF_INET; dest.sin_addr.s_addr = htonl(INADDR_LOOPBACK); dest.sin_port = htons(PORTNUM); if (connect(sockfd,(struct sockaddr*)&dest, sizeof(struct sockaddr_in)) == -1) { perror("connect"); return errno; } close(sockfd); } return EXIT_SUCCESS; } int test() { int ret = EXIT_SUCCESS; int spid = fork(); if (spid) { // parent : clients // wait for server to be listening while (WEXITSTATUS(system("netstat -tapen 2>/dev/null | grep ':2423' >/dev/null")) == 1) { sched_yield(); } ret = client(); kill(spid, SIGINT); int s_ret; waitpid(spid, &s_ret,0); return s_ret || ret; } else { // child : server server(); } return ret; } int main() { int i = 0; while (test() == EXIT_SUCCESS) { printf("%i\n",i++); } } On Fri, Apr 25, 2014 at 8:43 AM, Michael Kerrisk (man-pages) < mtk.manpa...@gmail.com> wrote: > William, this report is a little vague... Do you have a *minimal* > program that demonstrates the problem? >
#include <arpa/inet.h> #include <assert.h> #include <errno.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> const int PORTNUM = 2423; const int BACKLOG = 16; int in_socketfd; void handle(int interrupt) { sched_yield(); close(in_socketfd); exit(0); } void server() { // on SIGINT, exit cleanly struct sigaction term_act; term_act.sa_handler = handle; sigemptyset(&term_act.sa_mask); term_act.sa_flags = 0; if (sigaction(SIGINT, &term_act, NULL)) { perror("sigaction"); exit(errno); } in_socketfd = socket(AF_INET, SOCK_STREAM, 0); if (in_socketfd == -1) { perror("socket"); exit(errno); } struct sockaddr_in in_addr; memset(&in_addr,0,sizeof(in_addr)); in_addr.sin_family = AF_INET; in_addr.sin_addr.s_addr = htonl(INADDR_ANY); in_addr.sin_port = htons(PORTNUM); if (bind(in_socketfd, (struct sockaddr*)&in_addr, sizeof(struct sockaddr_in))) { perror("bind"); exit(errno); }; if (listen(in_socketfd,BACKLOG)) { perror("listen"); exit(errno); } while (1) { struct sockaddr_in dest; socklen_t dest_size = sizeof(struct sockaddr_in); int socketfd = accept(in_socketfd, (struct sockaddr*) &dest, &dest_size); if (socketfd == -1) { perror("accept"); exit(errno); } char placeholder[15]; assert(recv(socketfd, placeholder, 15, 0) == 0); close(socketfd); } } int client() { int i; for (i = 0; i < 50000; i++) { int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { perror("socket"); return errno; } struct sockaddr_in dest; memset(&dest,0,sizeof(dest)); dest.sin_family = AF_INET; dest.sin_addr.s_addr = htonl(INADDR_LOOPBACK); dest.sin_port = htons(PORTNUM); if (connect(sockfd,(struct sockaddr*)&dest, sizeof(struct sockaddr_in)) == -1) { perror("connect"); return errno; } close(sockfd); } return EXIT_SUCCESS; } int test() { int ret = EXIT_SUCCESS; int spid = fork(); if (spid) { // parent : clients // wait for server to be listening while (WEXITSTATUS(system("netstat -tapen 2>/dev/null | grep ':2423' >/dev/null")) == 1) { sched_yield(); } ret = client(); kill(spid, SIGINT); int s_ret; waitpid(spid, &s_ret,0); return s_ret || ret; } else { // child : server server(); } return ret; } int main() { int i = 0; while (test() == EXIT_SUCCESS) { printf("%i\n",i++); } }