簡體   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