套接字:如何通过select检测对等方的关闭(SD_RECEIVE)?

socket: how to detect peer's shutdown(SD_RECEIVE) by select?

当服务器调用shutdown(SD_SEND)时,客户端可以通过select和recv(returns 0)检测到。但是客户端如何检测关机(SD_RECEIVE)?

如果服务器关闭它的接收通道,它就不能再接收任何数据了。没有办法用 select() 来检测这种情况,除非套接字不再被报告为可写。在这种情况下没有信号发送到客户端(与关闭发送通道不同,它发送一个 FIN 数据包,指示不再发送数据)。因此,客户端之后发送数据的任何尝试都将在等待服务器确认有空间接收时无限期地缓冲,或者更有可能只是失败并出现错误。

简短回答:没有任何魔法 API 客户端可以用来检测(Microsoft!)服务器是否碰巧调用了 shutdown(SD_RECV)。但是,该套接字上从客户端到服务器的所有后续发送都将失败。

更长的答案:

  • shutdown(SD_RECV) 是 Windows 的东西。它不一定与一般的套接字有关,当然也与 TCP/IP 本身无关。没有 TCP-level FIN 或 RST。没有给客户的“消息”。

  • 来自文档:

https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-shutdown

The shutdown function does not close the socket. Any resources attached to the socket will not be freed until closesocket is invoked.

Another method to wait for notification that the remote end has sent all its data and initiated a graceful disconnect uses overlapped receive calls follows :

  1. Call shutdown with how=SD_SEND.
  2. Call recv or WSARecv until the function completes with success and indicates zero bytes were received. If SOCKET_ERROR is returned, then the graceful disconnect is not possible.
  3. Call closesocket.