套接字recv()函数

问题描述 投票:0回答:3

在c ++中,在windows OS中,对TCP套接字的recv()调用,如果套接字连接以某种方式关闭,recv()会立即返回还是挂起?

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

提前致谢。

c++ winsock winsock2
3个回答
1
投票

As documented取决于连接是如何关闭的,它应该或多或少立即在非优雅的情况下使用SOCKET_ERROR的返回值,并将WSAGetLastError设置为WSAENOTCONN之类的可能原因之一,或者只是在优雅连接关闭场景中返回0。阻塞和非阻塞套接字之间的情况相同。

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

但是,由于我知道Windows API并不总是按照文档记录的方式工作,因此我建议对其进行测试。


0
投票

如果你的recv()基于BSD - 几乎所有都是 - 它会在连接关闭时(根据本地方的状态)立即返回,无论套接字是阻塞还是非阻塞。


0
投票

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

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

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

如果您不想等待操作系统在内部超时,您可以在代码中始终使用自己的超时,例如通过select()setsocktopt(SO_RCVTIMEO),TCP keep-alives(setsockopt(SO_KEEPALIVE)WSAIoCtl(SIO_KEEPALIVE_VALS))等。您可能仍然无法获得立即失败,但你会很快得到它。

© www.soinside.com 2019 - 2024. All rights reserved.