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

Fla*_*ash 3 c sockets select posix network-programming

背景:我知道我不能直接打电话accept(),select()并假设它会起作用,因为客户端可能在select()返回后断开连接,即使select()告诉我套接字已准备就绪accept().相反,我需要设置套接字O_NONBLOCK,然后测试EAGAIN/EWOULDBLOCK我何时调用accept()- 见下文.

问题:我需要用select()/ 做同样的事情recv()吗?如果select()告诉我套接字已准备好读取,我是否可以调用recv()并保证它不会阻塞(或报告EAGAIN/EWOULDBLOCK它是否为非阻塞套接字)?

这是我用于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;
    }
Run Code Online (Sandbox Code Playgroud)

(select_for_read获取一个文件描述符和块的数组,直到一个准备好使用select().)

Jer*_*ner 5

Linuxselect手册页:

在Linux下,select()可以将套接字文件描述符报告为"准备好读取",而不是后续的读取块.这可能例如在数据到达时发生但在检查时
具有错误的校验和并被丢弃.可能存在其他情况,其中虚假地报告文件描述符为就绪.因此,在不应阻塞的套接字上使用O_NONBLOCK可能更安全.

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