简体   繁体   English

套接字recv()函数

[英]Socket recv() function

In c++, in windows OS, on the recv() call for TCP socket , if the socket connection is closed somehow, the recv() will return immediately or will it hang? 在c ++中,在Windows OS中,在对TCP socket的recv()调用上,如果套接字连接以某种方式关闭,则recv()将立即返回还是挂起?

What would be result(immediately returns or hangs) in the blocking and non blocking socket? 在阻塞和非阻塞套接字中会导致什么结果(立即返回或挂起)? I am using socket version 2. 我正在使用套接字版本2。

Thanks in advance. 提前致谢。

As documented depending of how the connection was closed it should more or less immediately with a return value of SOCKET_ERROR in a non graceful case and set WSAGetLastError to one of the possible reasons like WSAENOTCONN or would just return 0 in the graceful connection close scenario. 如所记录的那样,取决于连接的关闭方式,在非正常情况下,它应立即或多或少返回一个值SOCKET_ERROR并将WSAGetLastError设置为诸如WSAENOTCONN的可能原因之一,或者在正常连接关闭情况下仅返回0 This would be the same between blocking and nonblocking sockets. 阻塞套接字和非阻塞套接字之间是相同的。

If the socket is connection oriented and the remote side has shut down the connection gracefully, and all data has been received, a recv will complete immediately with zero bytes received. 如果套接字是面向连接的,并且远程端已正常关闭连接,并且已接收到所有数据,则recv将立即完成,并且接收到零字节。 If the connection has been reset, a recv will fail with the error WSAECONNRESET. 如果连接已重置,则接收将失败,并显示错误WSAECONNRESET。

However, since I know the Windows API does not always work as documented, I recommend to test it. 但是,由于我知道Windows API并不总是按文档所述运行,因此我建议对其进行测试。

如果您的recv()基于BSD(几乎都是基于BSD的),则无论连接是阻塞还是非阻塞,如果关闭连接(根据本地状态),它将立即返回。

recv() will return 0 upon a graceful disconnect, ie the peer shutdown its end of the connection and its socket stack sent a FIN packet to your socket stack. recv()正常断开连接时将返回0,即对等方关闭其连接结束,并且其套接字堆栈将FIN数据包发送到您的套接字堆栈。 You are pretty much guaranteed to get this result immediately, whether you use a blocking or non-blocking socket. 无论使用阻塞套接字还是非阻塞套接字,几乎可以保证您立即获得此结果。

recv() will return -1 on any other error, including an abnormal connection loss. recv()将在任何其他错误(包括异常的连接丢失recv()返回-1。 You need to use WSAGetLastError() to find out what actually happened. 您需要使用WSAGetLastError()来找出实际发生的情况。 For a lost connection on a blocking socket, you will usually get an error code such as WSAECONNRESET or WSAECONNABORTED . 对于阻塞套接字上的连接丢失,通常会收到错误代码,例如WSAECONNRESETWSAECONNABORTED For a lost connection on a non-blocking socket, it is possible that recv() may report an WSAEWOULDBLOCK error immediately and then report the actual error at some later time, maybe via select() with an exception fd_set , or an asynchronous notification, depending on how you implement your non-blocking logic. 对于非阻塞套接字上的连接丢失, recv()可能会立即报告WSAEWOULDBLOCK错误,然后在稍后的某个时间报告实际错误,可能是通过select()带有fd_set异常或异步通知,取决于您如何实现非阻塞逻辑。

However, either way, you are NOT guaranteed to get a failure result on a lost connection in any timely manner! 但是,无论哪种方式,都不能保证您及时获得丢失连接的故障结果! It MAY take some time (seconds, minutes, can even be hours in rare cases) before the OS deems the connection is actually lost and invalidates the socket connection. 操作系统认为的连接实际损失和插座连接失效前,可能需要一定的时间(几秒钟,几分钟,甚至可以在极少数情况下小时)。 TCP is designed to recover lost connections when possible, so it has to account for temporary network outages and such, so there are internal timeouts. TCP被设计为在可能的情况下恢复丢失的连接,因此它必须解决临时网络中断等问题,因此存在内部超时。 You don't see that in your code, it happens in the background. 您没有在代码中看到它,而是在后台发生。

If you don't want to wait for the OS to timeout internally, you can always use your own timeout in your code, such as via select() , setsocktopt(SO_RCVTIMEO) , TCP keep-alives ( setsockopt(SO_KEEPALIVE) or WSAIoCtl(SIO_KEEPALIVE_VALS) ), etc. You may still not get a failure immediately , but you will get it sooner rather than later. 如果您不想等待操作系统内部超时,则始终可以在代码中使用自己的超时,例如通过select()setsocktopt(SO_RCVTIMEO) ,TCP keep-alives( setsockopt(SO_KEEPALIVE)WSAIoCtl(SIO_KEEPALIVE_VALS) )等。您仍然可能不会立即失败,但是您会早日获得成功。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM