繁体   English   中英

pipe(),fork()和sleep()

[英]pipe(), fork(), and sleep()

在多个客户端请求上,给定的服务器代码应为每个客户端请求响应一个顺序号。 同样,对于每个客户端请求,服务器也应该派生一个进程。 然后,子进程等待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);
            }

    }

问题可能是在fork ,在父级中关闭了管道的两端,因此在无限循环的下一次迭代中,您尝试使用管道,但管道已经关闭。


您还应该处理收割子进程,否则它们将变成僵尸,直到父进程退出。 这可以通过为SIGCHLD安装信号处理程序并在信号处理程序调用wait

在父进程中,您尝试从一个空管道中read()read()将阻塞直到有可用数据为止,因此它将阻塞直到子进程唤醒并调用write()为止。 调用pipe()之后,向管道中写入一些内容,

pipe(fd);
write(fd[1], &num, sizeof(num));

它会解决您的问题。

约阿希姆·皮勒伯格(Joachim PIleborg)关于处理子进程的收获的观点很重要。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM