1. 程式人生 > >學習fifo管道,對read的一點總結

學習fifo管道,對read的一點總結

           按照unix網路程式設計第二版中的fifo管道例子,跑了一下,發現如下問題:

當server通過fifo管道把檔案內容發傳完給client後,client也正確接收完,server就退出,但client沒退出,還在死迴圈????

原因:client中的read呼叫是阻塞的,不會主動退了, 所以一直在監測管道的資料到來(不像socket那樣,一端關閉,另一端就會返回),其實它的確不知是否結束。

解決方法:要對方結束,就要在應用上處理,通過指定的協議,讓對方知道傳輸己結束,修改後的client和server如下:

void client(int readfd, int writefd)
{
        size_t len;
        size_t n;
        char buf[100];

       fgets(buf, 100, stdin);
       len = strlen(buf);
       if ('\n' == buf[len -1])
       {
              len--;
       }

       write(writefd, buf, len);

       while( (n = read(readfd, buf, 100)) > 0 )
       {
        write(STDOUT_FILENO, buf, n);

        if ( strcmp(buf, "over") == 0 )
        {
              break;
        }
     }
     std::cout << "client while over" << std::endl;
}

void server(int readfd, int writefd)
{
    int fd;
    size_t n;
    char buf[100];

    if ((n = read(readfd, buf, 100)) == 0)
    {
        std::cout << "end-of-file while reading pathname" << std::endl;
    }
    buf[n] = '\0';

    if ((fd = open(buf, O_RDONLY)) < 0)
    {
        snprintf(buf + n, sizeof(buf) - n, ": can't open, %s\n", strerror(errno));
        n = strlen(buf);
        write(writefd, buf, n);
    }
    else
    {
        while ( (n = read(fd, buf, 100)) > 0 )
        {
            write(writefd, buf, n);
        }
        write(writefd, "over", 5);

        std::cout << "server while over" << std::endl;
        close(fd);
    }
}

================================================================================================================

往後的例子看到,更好的辦法是:
        子程序把writefd關閉,這樣父過程client中的read呼叫就會返回。

注UNPv2中4.10節:

        在使用管道或FIFO時,可以通過關閉IPC通道來通知對方己到達輸入檔案的結尾。不過我們通過傳送回一個長度為0的訊息來達到同樣的目的,因為存在沒有檔案結束符概念的其他型別的IPC.