套接字recv()函数

时间:2019-02-20 13:29:13

标签: c++ winsock winsock2

在c ++中,在Windows操作系统中,在对TCP socket的recv()调用上,如果套接字连接以某种方式关闭,则recv()将立即返回还是挂起?

在阻塞和非阻塞套接字中会发生什么结果(立即返回或挂起)? 我正在使用套接字版本2。

谢谢。

3 个答案:

答案 0 :(得分:1)

As documented(取决于连接的关闭方式)在非正常情况下应立即或多或少以返回值SOCKET_ERROR并将WSAGetLastError设置为以下可能的原因之一: WSAENOTCONN,或者在正常连接关闭方案中仅返回0。阻塞套接字和非阻塞套接字之间是相同的。

  

如果套接字是面向连接的,并且远程端已正常关闭连接,并且已接收到所有数据,则recv将立即完成,并接收零字节。如果连接已重置,则接收将失败,并显示错误WSAECONNRESET。

但是,由于我知道Windows API并不总是按文档所述运行,因此我建议对其进行测试。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

recv()将在 graceful 断开连接后返回0,即对等方关闭其连接结束,并且其套接字堆栈将FIN数据包发送到您的套接字堆栈。无论您使用阻塞套接字还是非阻塞套接字,都可以保证立即获得此结果。

recv()将在任何其他错误(包括异常连接丢失)上返回-1。 您需要使用WSAGetLastError()来找出实际发生的情况。对于阻塞套接字上的连接丢失,通常会收到错误代码,例如WSAECONNRESETWSAECONNABORTED。对于非阻塞套接字上的连接丢失,有可能recv()可能立即报告WSAEWOULDBLOCK错误,然后在以后的某个时间报告实际错误,也许通过select()异常fd_set还是异步通知,具体取决于您如何实现非阻塞逻辑。

但是,无论哪种方式,都不能保证您及时丢失连接会导致失败!在操作系统认为连接实际上丢失并使套接字连接无效之前,可能要花一些时间(几秒钟,几分钟,甚至在几个小时内甚至是几个小时)。 TCP经过设计设计,可以在可能的情况下恢复丢失的连接,因此它必须考虑到临时的网络中断等情况,因此存在内部超时。您不会在代码中看到它,而是在后台发生。

如果您不想等待操作系统内部超时,则可以始终在代码中使用自己的超时,例如通过select()setsocktopt(SO_RCVTIMEO),TCP保持活动({ {1}}或setsockopt(SO_KEEPALIVE)),等等。您可能仍然没有立即失败,但是您会早日得到失败。