【问题标题】:Select with non-blocking reads选择非阻塞读取
【发布时间】:2015-05-05 06:36:07
【问题描述】:

我很难在网上找到答案。

在 Linux 上调用 select 读取文件并且套接字设置为非阻塞时应该发生什么 ?

正如选择手册页所述,我认为这不是微不足道的:

Those listed in readfds will be watched to see if characters become available for reading (more precisely, to see if a read will not block; in particular, a file descriptor is also ready on end-of-file)

如果套接字设置为非阻塞,它不应该阻塞,应该选择立即返回吗?这听起来不对……海德文档是错误的还是忽略了这种情况?

另外,如果 select 确实会阻塞,它的返回值应该是多少?读取套接字不会阻塞,但套接字没有可读取的数据..

当我回到家时,我会编写一些代码示例并编辑这个问题,这对其他任何在谷歌上搜索这个主题的人都有很大帮助。

【问题讨论】:

    标签: linux sockets select nonblocking


    【解决方案1】:

    这是一个小 C 程序,它显示在非阻塞文件描述符上调用 select(2) 仍然会阻塞,直到有要读取的内容:

    #include <stddef.h>
    #include <stdio.h>
    #include <sys/time.h>
    #include <sys/select.h>
    #include <unistd.h>
    #include <fcntl.h>
    
    int main(int argc, char **argv) {
        int ready;
        struct timeval *pto;
        fd_set readfds, writefds;
        char buf[1024];
        int bytes;
        int fd = 0; // stdin
    
        pto = NULL;
        FD_ZERO(&readfds);
        FD_ZERO(&writefds);
        FD_SET(fd, &readfds);
    
        int flags = fcntl(fd, F_GETFL, 0);
        fcntl(fd, F_SETFL, flags | O_NONBLOCK);
    
        while (1) { 
            ready = select(1, &readfds, &writefds, NULL, pto);
    
            if (ready == -1) {
                printf("got -1\n");
                return 1;
            }
    
            printf("ready = %d\n", ready);
    
            bytes = read(fd, buf, 1024);
            if (bytes == 0) {
                printf("all done\n");
                return 0;
            } else if (bytes > 0) {
                buf[bytes] = '\0';
                printf("read: %s\n", buf);
            } else {
                printf("got an error\n");
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      如果你在没有非阻塞的情况下使用read(),程序会阻塞,从而阻塞你的代码流。但是如果你使用非阻塞模式,select() 将立即返回,而不会阻塞代码流,仅当有一些数据要读取时才返回大于零的值。

      【讨论】:

      • 不,read() 会立即返回。 select() 将一直阻塞,直到某些内容可以选择或超时到期。
      • 不要在 cmets 中提出新问题。
      【解决方案3】:

      如果您 select() 在没有数据等待读取(也没有任何错误)的套接字上读取,它将阻塞(直到 select() 超时到期)。

      【讨论】:

      • 我就是这么想的,但我找不到任何支持它的东西..你可以吗?
      • 当然,任何有关事件驱动套接字编程的书都会解释这一点。我推荐已故 Richard Stevens 的 Unix Network Programming。
      • @ejp 我从选择手册页中引用的部分声明“如果读取不会阻塞”,在非阻塞情况下总是如此
      • @user1708860:手册页可能含糊不清或没有直接解决您关心的问题。如果您仍然不相信这就是它的工作原理,请自己尝试一下。
      • 在 Linux 上,如果读取将返回,则选择返回,因此对于没有可用数据的非阻塞流,选择将返回。这显然不是 POSIX 行为,但 Linux 不符合 POSIX。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-17
      • 2014-04-24
      • 2017-02-18
      • 1970-01-01
      • 1970-01-01
      • 2013-12-28
      相关资源
      最近更新 更多