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



让我们考虑以下代码

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); 
    }
}

现在我有两个关于上述代码的问题。

  1. 如果对poll()的调用既不返回-1也不返回0,并且在位图revents中为file_descriptors数组中的第一个条目设置了POLLIN标志,那么对recv()的调用会阻塞吗?如果没有,那么数据会立即读入吗
  2. 假设对CCD_ 7的调用以与上述相同的方式进行。将读入多少数据?这会和recv()的常规通话一样吗?即在上述情况下小于或等于CCD_ 9的任意量(对于程序员)。那么,如果我想在再次读取之前poll(),我是否只是从第一次调用poll()开始重复,直到所有数据都被完全读入(即,在客户端-服务器场景中,这将对应于正在完成的请求)

谢谢!

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

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

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

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

有三种常见的非阻塞I/O策略,您可以基于pollselect。所有这些都要求插座设置为无阻塞。

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

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

3) 在执行I/O操作之前,可以调用pollselect。然后,您尝试多次readwrite,直到您完成所有需要做的事情或得到"将阻止"指示。当您得到一个"将阻止"指示时,您要等到selectpoll告诉您,然后再在该套接字上尝试该方向的另一个操作。

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

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

如果poll()返回一个严格的正值,则意味着至少有一个描述符要返回一些数据。

因此,recv()不应该被阻塞:因为有数据,它应该返回一些东西。在任何情况下,都不能保证调用会返回所有1024个字节。

因此,您必须检查recv()返回的字节数。最终,你必须循环你的轮询/接收,直到你得到所有预期的数据。

您可以通过使用标志参数MSG_DONTWAIT的调用来控制阻塞/非阻塞行为,也可以通过更持久的fcntl()来控制。

编辑:请注意,如果套接字出现问题(例如,连接丢失),则轮询承诺的可用数据可能会丢失,并阻止recv()与所有预期相反。因此,明确使用非阻塞标志更安全(并考虑recv()可能返回错误代码,而不是读取的字节数)。

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

它不应该,除非另一个线程已经从套接字读取了当前可用的所有数据。

如果没有,那么数据会立即读入吗?

是的。

假设对CCD_ 46的调用以与上述相同的方式进行。将读入多少数据?

与已经到达的数据一样多。

这会和recv()的常规通话一样吗?即在上述情况下小于或等于1024的任意量(对于程序员)。

是的。

那么,如果我想在再次读取之前poll(),我是否只是从第一次调用poll()开始重复,直到所有数据都被完全读入(即,在客户端-服务器场景中,这将对应于正在完成的请求)?

是的。

相关内容

最新更新