pipe(),fork()和sleep()

时间:2014-05-14 11:52:53

标签: c fork pipe

在多个客户端请求上,给定的服务器代码应响应每个客户端请求的序号。此外,对于每个客户端请求,服务器应该分叉进程。子进程然后等待5秒并减少客户端请求计数。所以基本上它是一个令牌系统。

代码中的问题是,当我发送多个客户端请求时,除了第一个请求之外,其他人被阻止了5秒,这是我不想要的。

static int num = 0;

int main(int ac, char *av[]){

    struct sockaddr_in saddr;
    struct hostent *hp;
    char hostname[HOSTLEN];
    int sock_id, sock_fd;
    FILE *sock_fp;
    int pid, fd[2];
    pipe(fd);

    sock_id = socket(PF_INET, SOCK_STREAM, 0);
    if(sock_id == -1)
            oops("Socket");

    bzero((void *)&saddr, sizeof(saddr));

    gethostname(hostname, HOSTLEN);
    hp = gethostbyname(hostname);

    bcopy((void *)hp->h_addr, (void *)&saddr.sin_addr, hp->h_length);
    saddr.sin_port = htons(PORTNUM);
    saddr.sin_family = AF_INET;

    if(bind(sock_id, (struct sockaddr *)&saddr, sizeof(saddr)) != 0)
            oops("bind");

    if(listen(sock_id, 5) != 0)
            oops("listen");
    while(1) {
            sock_fd = accept(sock_id, NULL, NULL);
            printf("got a call\n");
            if(sock_fd == -1)
                    oops("accept");

            num++;

            sock_fp = fdopen(sock_fd, "w");
            if(sock_fp == NULL)
                    oops("fdopen");
            fprintf(sock_fp, "Your token number is: %d\n", num);
            fclose(sock_fp);

            pid = fork();

            if(pid == 0){
                    close(sock_id);
                    sleep(5);
                    num--;

                    close(fd[0]);
                    write(fd[1], &num, sizeof(num));
                    printf("Sent: %d\n", num);
                    close(fd[1]);
                    exit(0);
            }
            else if(pid > 0){
                    close(fd[1]);
                    read(fd[0], &num, sizeof(num));
                    printf("Received %d\n", num);
                    close(fd[0]);
                    close(sock_fd);
            }

    }

2 个答案:

答案 0 :(得分:0)

问题可能是在fork之后,在父级中你关闭管道的两端,所以无限循环的下一次迭代你尝试使用管道但是它已经关闭了。 / p>


您还应该处理子进程的收获,否则它们将成为僵尸,直到父进程退出。这可以通过为SIGCHLD和信号处理程序调用{​​{3}}安装信号处理程序来完成。

答案 1 :(得分:0)

在父进程中,您尝试从空管道读取,read()将阻塞直到数据可用,因此它会阻塞,直到子进程唤醒并调用write()。在致电pipe()

后,将内容写入管道
pipe(fd);
write(fd[1], &num, sizeof(num));

它会解决你的问题。

Joachim Pileborg关于处理儿童过程收获的说法很重要。