我在非阻塞模式下有一个连接的TCP套接字。发送和接收数据的工作正常。接收被实现为专用线程上的循环,因此:select()有时会阻塞超过所提供的超时时间
fd_set fdset;
FD_ZERO(&fdset);
FD_SET(internal->m_socket, &fdset);
struct timeval timeout;
timeout.tv_sec = timeout_ms/1000;
timeout.tv_usec = (timeout_ms % 1000) * 1000;
int ret = select(internal->m_socket + 1, &fdset, nullptr, nullptr, &timeout);
if (ret == 0) {
// handle timeout then loop
} else if (ret < 0) {
// handle error then abort
} else {
ret = recv(...); // Read data available on socket then loop
}
TCP连接从运行OS X 10.11.5的MacBookPro转到WiFi。当连接建立时关闭WiFi时,一些后续select()
调用可能需要比指定的超时值更长的时间。
这里加入日志调用的证明(IN
和OUT
之前分别印刷select()
在超时值传递与实际测量的经过时间后):
(WiFi is ON, thread is continuously receiving from socket)
08:31:15 -------- IN = 15000
08:31:30 -------- OUT = 14999
08:31:30 -------- IN = 15000
08:31:45 -------- OUT = 15000
08:31:45 -------- IN = 15000
08:32:00 -------- OUT = 15000
08:32:00 -------- IN = 15000
08:32:15 -------- OUT = 15002
08:32:15 -------- IN = 1000
08:32:15 -------- OUT = 87 <--- data received
08:32:15 -------- IN = 4913
08:32:15 -------- OUT = 0 <--- data received
08:32:15 -------- IN = 15000
(WiFi is turned OFF at this point in the middle of a `select()` call)
08:32:30 -------- OUT = 15004 <--- ok
08:32:30 -------- IN = 1000
08:32:31 -------- OUT = 1003 <--- ok
08:32:31 -------- IN = 1000
08:32:32 -------- OUT = 1006 <--- ok
08:32:32 -------- IN = 1000
08:32:43 -------- OUT = 10999 <--- NOT OK: 10X longer
08:32:43 -------- IN = 1000
08:32:48 -------- OUT = 4965 <--- NOT OK: 5X longer
(truncated)
注意,没有明显模式:有时候这个错误似乎不会发生,但大多数情况下确实如此。在关闭WiFi之后,它可以是紧接着的select()
呼叫,该WiFi需要比指定的超时更长的时间,或者之后的一个或更多时间。
您的选择超时只有一秒?为什么? – EJP
这段代码上面有很多代码,如果接收超时,其他逻辑运行。例如,我默认使用15秒超时,但如果应用程序认为连接不工作,它会向服务器发送一个Ping,然后将超时减少到1秒,等待Pong几秒钟,并终止连接没收到。 – Pol
这可能是App Nap。查看活动监视器的“能量”选项卡是否显示您的应用程序在问题发生时处于暂停状态。 –