在客户端-服务器程序中,需要在 read() 上检查 EOF FIFO 吗?

问题:

  • FIFO 中的 EOF 是否返回 0 或带有 errno 设置的 -1
  • 该规则是否也适用于其他 IPC 设施?


  • @更新

    我仍然发现结果有效,所以需要继续询问它。

    以下是源代码:

    cs_fifo.h:
    // fifo header
    #ifndef _CS_FIFO
    #define _CS_FIFO
    
    #define CLIENT_DATA_SIZE 2
    #define SERVER_DATA_SIZE 10
    
    #define SERVER_FIFO_PATH "/tmp/server_fifo"
    
    #define CLIENT_COUNT 3
    
    #endif
    

    fifo_server.c:
    // client - server fifo, server part,
    #include <stdio.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include "cs_fifo.h"
    
    int fifo_server() {
        int flag;
        int fd;
    
        char buf[CLIENT_DATA_SIZE];
    
        // remove fifo, before create
        remove(SERVER_FIFO_PATH);
    
        // create fifo
        mode_t mode = 0644;
        if((flag = mkfifo(SERVER_FIFO_PATH, mode)) == -1) {
            printf("error while mkfifo(): %s\n", strerror(errno));
            return -1;
        }
        printf("server fifo created, path: %s\n", SERVER_FIFO_PATH);
    
        // open for read
        if((fd = open(SERVER_FIFO_PATH, O_RDONLY)) == -1) {
            printf("error while open(): %s\n", strerror(errno));
            exit(-1);
        }
    
        // loop to receive data from client,
        while(1) {
            // read from fifo
            if((flag = read(fd, buf, CLIENT_DATA_SIZE)) == -1) {
                printf("error while read(): %s\n", strerror(errno));
                exit(0);
            } else if(flag == 0) { // no data
                printf("no data\n");
                sleep(1);
                continue;
            }
            // data received,
            printf("receive data: %s\n", buf);
    
            // send data back to client's fifo,
            // TODO
        }
    
        // remove fifo, after finish using,
        remove(SERVER_FIFO_PATH);
    
        return 0;
    }
    
    int main(int argc, char * argv[]) {
        return fifo_server();
    }
    

    fifo_client.c:
    // client - server fifo, client pool part,
    #include <stdio.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include "cs_fifo.h"
    
    int fifo_client_pool() {
        int flag;
        int server_fd;
    
        char data[CLIENT_DATA_SIZE];
    
        int i = 0;
        pid_t cpid;
        char identity;
    
        // open for write
        if((server_fd= open(SERVER_FIFO_PATH, O_WRONLY)) == -1) {
            printf("error while open(): %s\n", strerror(errno));
            exit(-1);
        }
    
        // create child processes as clients,
        while(i < CLIENT_COUNT) {
            switch(cpid=fork()) {
                case -1: // failed
                    printf("error while fork(): %s\n", strerror(errno));
                    exit(errno);
                case 0: // success, child process goes here
                    printf("child process created, pid [%d], parent pid [%d]\n",(int)getpid(), (int)getppid());
                    identity = i + 65; // start from 'A'
    
                    // prepare data
                    data[0] = identity;
                    data[1] = '\0';
    
                    // write to fifo
                    if((flag = write(server_fd, data, CLIENT_DATA_SIZE)) == -1) {
                        printf("[%c] error while write(): %s\n", identity, strerror(errno));
                        _exit(-1);
                    }
                    printf("[%c] send data to server\n", identity);
    
                    _exit(0);
    
                    break;
                default: // success, parent process goes here
                    // sleep a while,
                    sleep(1);
                    break;
            }
    
            i++;
        }
    
        if((flag = close(server_fd)) != 0) {
            printf("error while close(): %s\n", strerror(errno));
        }
    
        return 0;
    }
    
    int main(int argc, char * argv[]) {
        return fifo_client_pool();
    }
    

    编译:

    服务器:gcc -Wall fifo_server.c -o server
    客户:gcc -Wall fifo_client_pool.c -o client_pool
    执行:

    首先启动服务器:./server
    然后启动客户端池:./client_pool
    结果:
  • 服务器启动,在客户端启动前阻塞。
  • 然后client启动,server从3个client中的每一个收到1个请求,总共3个。
  • 然后所有客户端进程终止,然后服务器的 read() 继续返回 0 而不阻塞。


  • future 的问题是:
  • 在所有客户端终止后,服务器的 read() 不应该阻塞吗?因为它处于阻塞模式?
  • 最佳答案

    read 返回零的描述符中读取的所有内容都表示“关闭”或“结束”。

    如果您有一个阻塞描述符(默认),那么 read 将在当前没有任何内容可读取时阻塞。如果描述符是非阻塞的,那么 read 返回 -1errno 设置为 EAGAINEWOULDBLOCK 如果没有任何内容可读取。

    关于c - 如何在 FIFO 上的 read() 时检查 EOF,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34327018/

    10-14 09:55
    查看更多