【发布时间】:2016-11-17 17:15:23
【问题描述】:
我正在使用下面的代码在套接字上接收。 recv() 返回接收到的零字节,这意味着连接已断开,但它看起来不像:
while( true )
{
buffer = onGetBuffer( maxBytesToRecv );
const int flags = MSG_WAITALL;
errno = 0;
const ssize_t bytesReceived = ::recv( descriptor() , buffer , maxBytesToRecv , flags );
if ( bytesReceived > 0 ){
processData( receivedTime , bytesReceived );
}
else if ( bytesReceived < 0 ){
const int eno = errno;
if ( EINTR != eno ){
// Log error code
}
}
else{
// Peer disconnected
// ** Code is reaching here **
}
}
我正在点击分支,暗示对等方已断开连接,因为bytesReceived 为零。我检查了一个 pcap 转储,但我们没有收到 TCP FIN 消息来关闭连接。
在此期间我运行了 strace(过滤网络消息)以检查我们自己没有关闭连接以及它记录的有问题的套接字:
sendto(16, "DATA"..., 88, MSG_NOSIGNAL, NULL, 0) = 88
sendto(16, "DATA"..., 88, MSG_NOSIGNAL, NULL, 0) = 88
sendto(16, "DATA"..., 5584, MSG_NOSIGNAL, NULL, 0) = 5584
sendto(16, "DATA"..., 5654, MSG_NOSIGNAL, NULL, 0) = 5654
sendto(16, "DATA"..., 5651, MSG_NOSIGNAL, NULL, 0) = 5651
sendto(16, "DATA"..., 5593, MSG_NOSIGNAL, NULL, 0) = 5593
sendto(16, "DATA"..., 5635, MSG_NOSIGNAL, NULL, 0) = 5635
sendto(16, "DATA"..., 5563, MSG_NOSIGNAL, NULL, 0) = 5563
sendto(16, "DATA"..., 5608, MSG_NOSIGNAL, NULL, 0) = 5608
sendto(16, "DATA"..., 5662, MSG_NOSIGNAL, NULL, 0 <unfinished ...>
sendto(16, "DATA"..., 5583, MSG_NOSIGNAL, NULL, 0) = 5583
sendto(16, "DATA"..., 5579, MSG_NOSIGNAL, NULL, 0) = 5579
sendto(16, "DATA"..., 3373, MSG_NOSIGNAL, NULL, 0) = 3373
sendto(16, "DATA"..., 201, MSG_NOSIGNAL, NULL, 0) = 201
recvfrom(16, "DATA"..., 7126, MSG_WAITALL, NULL, NULL) = 7126
recvfrom(16, "DATA"..., 6187, MSG_WAITALL, NULL, NULL) = 6187
recvfrom(16, "DATA"..., 7079, MSG_WAITALL, NULL, NULL) = 7079
recvfrom(16, "", 0, MSG_WAITALL, NULL, NULL) = 0
其中 16 是套接字的描述符。最后可以看到最终receive返回0。
如果我们自己没有断开连接并且我们没有收到来自另一端的 TCP FIN 来断开我们的连接。没有返回错误代码,errno 也是零。
如果没有断开连接,为什么recv() 返回零?或者我还能检查什么?
【问题讨论】:
-
您已标记 [c],但由于将
recv()引用为::recv(),因此您的代码无效 C。 -
recvfrom(16, "", 0, MSG_WAITALL, NULL, NULL) = 0 告诉我你请求了 0 个字节,而你得到了 0 个字节
-
您是如何得出没有收到 TCP FIN 的结论的?
-
是的,使用可能看起来确实是错误的。如果它完成了我认为您正在优化程序以使错误代码成为快速路径。
-
@JohnBollinger recv() 是 GNU c 库的一部分,您抱怨问题被标记为......... C.