我使用以下代码在套接字上接收。 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是套接字的描述符。最后,您可以看到最终的收到返回0。
如果我们没有断开连接,我们没有从另一方收到TCP FIN来断开我们的连接。没有返回错误代码,errno
也为零。
如果没有断开连接,为什么recv()
会返回零?或者我还能检查什么?
答案 0 :(得分:4)
您的最终recv
来电是0字节。
来自Linux上的recv手册页:
如果从流套接字接收的请求字节数为0,则也可以返回值0。
作为对该计划的评论,我认为maxBytesToRecv
是一种奇怪的全球或阶级成员。如果程序信任数据流来声明这些块的大小,它看起来也可能是一个巨大的安全漏洞。
信任,但验证。边界检查长度值。处理零尺寸以解决此问题,但也检查太大的尺寸。由于巨大的值和整数溢出,已经发生了许多很多漏洞。或者更糟糕的是,将无符号长度复制到有符号整数中,并将0xFFFF视为65535某些地方和-1其他地方。
答案 1 :(得分:0)
最后一次调用 recv() 是否要求长度为零?
recvfrom(16, "", 0, MSG_WAITALL, NULL, NULL) = 0
如果您询问零字节,则您收到零字节。