在c ++中,在Windows操作系统中,在对TCP socket的recv()调用上,如果套接字连接以某种方式关闭,则recv()将立即返回还是挂起?
在阻塞和非阻塞套接字中会发生什么结果(立即返回或挂起)? 我正在使用套接字版本2。
谢谢。
答案 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()
来找出实际发生的情况。对于阻塞套接字上的连接丢失,通常会收到错误代码,例如WSAECONNRESET
或WSAECONNABORTED
。对于非阻塞套接字上的连接丢失,有可能recv()
可能立即报告WSAEWOULDBLOCK
错误,然后在以后的某个时间报告实际错误,也许通过select()
异常fd_set
还是异步通知,具体取决于您如何实现非阻塞逻辑。
但是,无论哪种方式,都不能保证您及时丢失连接会导致失败!在操作系统认为连接实际上丢失并使套接字连接无效之前,可能要花一些时间(几秒钟,几分钟,甚至在几个小时内甚至是几个小时)。 TCP经过设计设计,可以在可能的情况下恢复丢失的连接,因此它必须考虑到临时的网络中断等情况,因此存在内部超时。您不会在代码中看到它,而是在后台发生。
如果您不想等待操作系统内部超时,则可以始终在代码中使用自己的超时,例如通过select()
,setsocktopt(SO_RCVTIMEO)
,TCP保持活动({ {1}}或setsockopt(SO_KEEPALIVE)
),等等。您可能仍然没有立即失败,但是您会早日得到失败。