poll()系统调用以及之后接收或发送数据的行为

Cur*_*ous 7 c++ sockets networking tcp c++11

让我们考虑下面的代码

pollfd file_descriptors[1];
file_descriptors[0].fd = sock_fd;
file_descriptors[0].events = POLLIN;

int return_value = poll(file_descriptors, 1, 0);

if (return_value == -1) { cerr << strerror(errno); }
else if (return_value == 0) { cerr << "No data available to be read"; }
else { 
    if (file_descriptors[0].revents & POLLIN) {
        recv(sock_fd, buff, 1024, 0); 
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我对上面的代码有两个问题.

  1. 如果对poll()的调用既不返回也-1没有在数组中的第一个条目的位图中0设置POLLIN标志,那么调用是否会阻塞?如果不是,那么数据是否会即时读取?reventsfile_descriptorsrecv()
  2. 假设呼叫poll()的方式与上面提到的相同.要读入多少数据?它只是和普通电话一样recv()吗?即1024在上述情况下小于或等于任意(对程序员)的数量.然后,如果我想poll()再次阅读之前,我是否只是从第一次调用开始重复,poll()直到完全读取所有数据(即在客户端服务器方案中,这将对应于正在完成的请求)?

谢谢!

Dav*_*rtz 3

如果对 poll() 的调用既不返回 -1 也不返回 0,并且在位图中为 file_descriptors 数组中的第一个条目设置 POLLIN 标志,那么对 recv() 的调用会阻塞吗?如果不是,那么数据会立即读入吗?

对 的调用poll对对 的调用没有影响recv。是否recv阻塞取决于调用时有哪些数据可用recv以及套接字是否处于阻塞或非阻塞模式。

假设对 poll() 的调用与上面提到的方式相同。将读入多少数据?它与常规调用 recv() 一样吗?即在上述情况下,任意(对程序员而言)数量小于或等于 1024。那么,如果我想在再次读取之前进行 poll() ,我是否只需从第一次调用 poll() 开始重复,直到所有数据都已完全读入(即在客户端服务器场景中,这将对应于正在完成的请求)?

假设您不想阻塞,则应该将套接字设置为非阻塞。你有两个基本选择。您可以调用一次接收函数,然后poll再次调用。或者,您可以继续拨打接收电话,直到收到“将阻止”指示。如果套接字是 TCP 连接,您可以继续调用接收函数,直到收到“将阻塞”指示或接收到的字节数少于您要求的字节数。

poll您可以基于或三种常见的非阻塞 I/O 策略select。所有这些都要求套接字设置为非阻塞。

1) 您始终可以在执行 I/O 操作之前调用poll或。然后,仅当您从 或select获得读或写命中时,才尝试单个读或写操作。pollselect

2) 您可以先尝试readwrite操作。如果立即成功,那就太好了。如果没有,请等待pollselect点击后再重试该操作。

3) 您可以在执行 I/O 操作之前调用poll或。select然后,您尝试多次readwrite直到完成您需要做的所有事情或得到“将阻止”指示。当您收到“将阻塞”指示时,您会等到selectpoll告诉您,然后再尝试在该套接字上沿该方向执行其他操作。

方法 3 可能是最常见的读取方法。方法 2 可能是最常见的写入方法。

请记住,这poll是一个状态报告功能,可以告诉您当前信息,这一点非常重要。它不提供任何未来保证。读取指示意味着poll未来的读取操作不会阻塞的假设是一个错误,并且它在过去已经导致了严重的错误,并带来了重大的安全隐患。保证套接字操作不会阻塞的唯一方法是将套接字设置为非阻塞。