为什么我应该在关闭套接字之前使用shutdown()?

新手上路,请多包涵

在这个 MSDN 页面上:

在客户端发送和接收数据

它建议使用以下方法关闭套接字的发送端:

 shutdown(SOCK_ID, SD_SEND);

我为什么要?

也许我不必,它只是一个建议?也许是为了节省内存?也许是为了速度?

有人有想法吗?

原文由 fdwfg wdfwdfv 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 715
2 个回答

答案在 shutdown() 文档中:

如果 how 参数是 SD_SEND ,则不允许后续调用 send 函数。 对于 TCP 套接字,一个 FIN 将在所有数据发送并由接收方确认后发送

为了确保在连接的套接字关闭之前发送和接收所有数据,应用程序应在调用 closesocket 之前使用 shutdown 关闭连接。等待通知远程端已发送其所有数据并启动正常断开连接的一种方法使用 WSAEventSelect 函数,如下所示:

  1. 调用 WSAEventSelect 注册 FD_CLOSE 通知。
  2. 调用 shutdownhow=SD_SEND
  3. 当接收到 FD_CLOSE 时,调用 recvWSARecv 直到函数成功完成并指示接收到零字节。如果返回 SOCKET_ERROR ,则无法正常断开连接。
  4. 致电 closesocket

另一种等待通知远程端已发送其所有数据并启动正常断开连接的方法使用重叠接收调用如下:

  1. 调用 shutdownhow=SD_SEND
  2. 调用 recvWSARecv 直到函数成功完成并指示接收到零字节。如果返回 SOCKET_ERROR ,则无法正常断开连接。
  3. 致电 closesocket

有关详细信息,请参阅有关 正常关闭、Linger 选项和套接字关闭 的部分。

换句话说,至少对于 TCP,调用 shutdown(SD_SEND) 会通知对等方您已完成发送更多数据,并且您可能很快就会关闭连接端。最好,同伴也会为你做同样的礼貌。这样,两个对等点都可以知道连接在两端是有意关闭的。这称为 正常 断开连接,而不是 中止异常 断开连接。

默认情况下,如果您不调用 shutdown(SD_SEND) , --- closesocket() 将尝试为您执行正常关闭, 除非 套接字的延迟选项被禁用。最好不要依赖这种行为,在调用 shutdown() 之前,您应该始终自己调用 closesocket() ,除非您有充分的理由不这样做。

原文由 Remy Lebeau 发布,翻译遵循 CC BY-SA 3.0 许可协议

没有与套接字上的发送或接收操作相关的特定资源,套接字要么被使用,要么被关闭。关闭的原因与资源管理无关。关闭套接字是所谓的优雅关闭协议的实现,它允许通信双方意识到连接正在关闭,并允许最大限度地减少数据丢失。

原文由 SergeyA 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题