我可以保证在select()报告套接字准备好读取后,recv()不会阻塞吗?

时间:2014-05-10 06:30:58

标签: c sockets select network-programming posix

背景:我知道我无法在accept()之后立即致电select()并假设它可以正常运行,因为客户端可能已断开连接在select()返回后,即使select()告诉我套接字已准备好accept()。相反,我需要将套接字设置为O_NONBLOCK,然后在调用EAGAIN/EWOULDBLOCK时测试accept() - 请参阅下文。

问题:我是否需要对select() / recv()做同样的事情?如果select()告诉我套接字已准备好阅读,我可以致电recv()并保证它不会阻止(或报告EAGAIN/EWOULDBLOCK如果它是非阻塞套接字)?< / p>

以下是我用于accept()案例的代码:

    while(true) {
        fd_ready = select_for_read(listen_fds, 2);
        fd_client = accept(fd_ready, (struct sockaddr *)&client_addr, &client_addr_len);
        if (fd_client == -1) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                continue;
            } else {
                exit_with_error("Error accepting connection from client");
            }
        }
        break;
    }

select_for_read获取一组文件描述符和块,直到有一个文件描述符和块被准备好使用select()读取。)

1 个答案:

答案 0 :(得分:5)

来自select man page for Linux

  

在Linux下,select()可以将套接字文件描述符报告为&#34;就绪   用于读取&#34;,然而是随后的读取块。这可以   例如,当数据到达但是经过检查时发生   有错误的校验和,并被丢弃。可能还有其他情况   其中文件描述符被虚假报告为就绪。就这样吧   在不应阻塞的套接字上使用O_NONBLOCK可能更安全。

当然,这个警告是在错误部分,暗示作者认为这不是预期的行为 - 但是,在Linux下,至少它是可能发生的事情。就个人而言,我总是将我的插座设置为非阻塞;这样我就不必担心我的程序会意外阻塞除我打算阻止的地方之外的任何地方(即在select()内部。