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++);
    }
}

Reply via email to