【问题标题】:Reason for not properly closed socket?未正确关闭套接字的原因?
【发布时间】:2011-02-06 17:18:29
【问题描述】:

这是我想要做的: 当有新消息可用时,服务器会向连接的客户端发送消息。另一方面,客户端在连接时会尝试使用 send() 向服务器发送消息,然后使用 recv() 接收消息,然后客户端调用 close() 关闭连接。

有时,在客户端完成后,服务器尝试从客户端接收消息会导致 104 - “对等连接重置”错误。发生这种情况时,Wireshark 显示客户端发送的最后两个段是:
1. 确认收到服务器发送的消息的 ACK
2. RST/ACK
客户端不发送任何 FIN。

为什么会发生这种情况以及如何在客户端“正确”关闭套接字?

【问题讨论】:

    标签: sockets reset


    【解决方案1】:

    如果您在客户端调用close() 并且数据仍在接收队列中,则会发生这种情况。客户端将发送 RST 而不是 FIN,以表明并非所有数据都已成功交付给应用程序。如果连接只是为了客户端的利益,那么服务器可能不在乎;由于该套接字上无法进行进一步的通信,服务器应该简单地关闭它。

    可以通过如下方式关闭连接来避免这种情况(其中 A 是启动关闭的一方):

    • 当 A 发送完所有数据后,它会调用shutdown(sock, SHUT_WR) 并继续从套接字读取。
    • 当 B 看到 EOF(例如 recv() 返回 0)时,它知道 A 正在启动关闭。 B 发送任何最终响应或其他适用的最终数据,调用shutdown(sock, SHUT_WR),然后调用close(sock)
    • 当 A 看到 EOF 时,如果它已经关闭写入,它只会调用 close(sock)

    请注意,ECONNRESET 仍然是可能的,例如,如果另一个进程被杀死,那么它仍然必须被处理。在这种情况下,发送任何最终响应是没有意义的,因为对方不会收到它,所以在这种情况下应该关闭套接字。

    【讨论】:

    • 感谢您的回答。这正是我遇到的。您能否详细说明“当 B 看到 EOF 时,它知道 A 正在启动关机”?我应该如何在我的代码中这样做?
    • 没关系。我在这里找到了答案(2.6):faqs.org/faqs/unix-faq/socket
    • 如果调用recv()read(),这些接口返回0表示EOF。
    猜你喜欢
    • 2018-12-14
    • 1970-01-01
    • 1970-01-01
    • 2012-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-25
    • 2011-06-29
    相关资源
    最近更新 更多