【问题标题】:Proper way to close a socket to avoid "connection reset by peer"关闭套接字以避免“对等连接重置”的正确方法
【发布时间】:2015-03-27 01:42:50
【问题描述】:

我有一个持续维护套接字的客户端/服务器应用程序。当客户端退出时,它会向服务器发送一个“退出”消息,然后关闭套接字并进行清理。服务器在收到此消息时清理并关闭套接字 - 并且不回复该消息。

在相当定期的情况下,我看到服务器记录了“对等连接重置”错误,而最终用户没有任何投诉,我认为这一定是我的签核序列中偶尔出现的时间问题。当最终用户抱怨他们的连接实际上被丢弃时,我确实看到了同样的错误,所以我想知道如何区分这些场景之间的区别——或者更好的是,如何在正常情况下防止虚假的“连接重置”场景。

我猜在某些情况下,服务器会在收到“signing off”消息之前(或期间)被关闭的套接字击中。这可能吗?在实际关闭套接字之前,您是否应该遵循适当的顺序让服务器知道客户端即将终止?有什么方法可以在关闭之前检查最后一条消息是否已传递?

谢谢, 抢

【问题讨论】:

    标签: sockets


    【解决方案1】:

    shutdown(s, SHUT_RDWR) 函数应该可以解决您的问题。 this document有更完整的解释。

    【讨论】:

    • 很有趣,但不确定是否相同。该文档显示客户端在服务器关闭套接字后调用 recv() 时出错。我在服务器而不是客户端上收到“连接重置”错误。客户端调用 send() 然后 close(),服务器有时会收到“连接重置”错误。我的服务器(在 AIX 上)使用 poll() 函数处理多个套接字,并且连接重置错误是对 poll() 的响应。如果首先收到客户端的“signoff”消息,服务器会读取它,关闭套接字并将其从传递给 poll() 的列表中删除。
    • 一种可能性,不过。我的服务器每隔 2 分钟左右不活动后会偶尔发送“keepalive”应用程序消息(不是 TCP keepalives)。我想可能有一个时间窗口,客户端在不读取已经在传输中的 keepalive 的情况下尝试签核(发送/关闭)。这会导致服务器出现连接重置错误吗?
    • 已经很久了,我不记得poll()select()的比较,但我在想的是客户端close()s没有shutdown(),所以poll() 检查套接字(在其一侧标记为打开)的输入,并对连接被重置感到惊讶。 keepalive 可能是相关的,但不应该是相关的,因为据我所知,它只是一个要在关闭之前读取的数据包。
    【解决方案2】:

    这通常意味着您要么已写入已被对等方关闭的连接,要么在未读取所有待处理的传入数据的情况下关闭了连接。换句话说,应用程序协议错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-30
      • 2018-11-12
      • 2012-10-10
      • 1970-01-01
      • 2013-02-21
      • 2017-02-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多