让我们考虑以下代码
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);
}
}
现在我有两个关于上述代码的问题。
- 如果对poll()的调用既不返回
-1
也不返回0
,并且在位图revents
中为file_descriptors
数组中的第一个条目设置了POLLIN
标志,那么对recv()
的调用会阻塞吗?如果没有,那么数据会立即读入吗 - 假设对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策略,您可以基于poll
或select
。所有这些都要求插座设置为无阻塞。
1) 在执行I/O操作之前,始终可以调用poll
或select
。然后,只有当您从poll
或select
获得读取或写入命中时,才尝试单个读取或写入操作。
2) 您可以先尝试read
或write
操作。如果它立即成功,那就太好了。如果没有,请等待poll
或select
命中,然后重试该操作。
3) 在执行I/O操作之前,可以调用poll
或select
。然后,您尝试多次read
或write
,直到您完成所有需要做的事情或得到"将阻止"指示。当您得到一个"将阻止"指示时,您要等到select
或poll
告诉您,然后再在该套接字上尝试该方向的另一个操作。
方法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()
开始重复,直到所有数据都被完全读入(即,在客户端-服务器场景中,这将对应于正在完成的请求)?
是的。