【问题标题】:TIME_WAIT with boost asioTIME_WAIT 与提升 asio
【发布时间】:2016-05-02 13:44:20
【问题描述】:

我尝试了官方的 tcp echo 服务器示例serverclient。使用netstat -ano | findstr TIME_WAIT,我可以看到客户端每次都会导致 TIME_WAIT,而服务器则完全断开连接。

有没有办法防止 TIME_WAIT 或 CLOSE_WAIT 让双方都完全断开连接?

这是捕获的数据包,似乎最后一个ACK发送正确,但客户端仍然有TIME_WAIT

【问题讨论】:

    标签: c++ tcp boost-asio


    【解决方案1】:
    • CLOSE_WAIT 是一个编程错误。本地应用程序已收到传入关闭,但尚未关闭此端。

    • TIME_WAIT 在双方完全断开连接后出现,并且仅持续几分钟。避免它的方法是成为接收第一个关闭的结束。通常你想在服务器上避免它,所以你首先关闭客户端。

    【讨论】:

    • 所以,对于我的服务器,我猜客户端的TIME_WAIT是正常行为,也是最好的结果,两边都不能CLEAN,我的意思是没有XXX_WAIT或任何其他状态。跨度>
    • 您需要摆脱 TIME_WAIT 不是“干净”的观念。它是 TCP 精心设计的特性,对其正确工作至关重要。至少从美学上讲,最好将其转移到不会被注意到的客户端,而不是堆积在肯定会的服务器上。
    【解决方案2】:

    长时间挥之不去的 CLOSE_WAIT 确实是一个编程错误(操作系统执行连接关闭,但您的应用程序不记得及时释放套接字 - 或者根本不记得)。

    然而,TIME_WAIT 并不是真正的例外情况。有必要在正常连接关闭期间对可能丢失最后一个 ACK​​ 段的连接提供干净的关闭。如果没有它,FIN+ACK 段的重传将通过连接重置来响应,一些敏感的应用程序可能不喜欢它。

    让 TIME_WAIT 状态的套接字数量较少的最常见方法是通过调整全局 OS 级别参数来全局缩短其持续时间。 IIRC,还有一种方法可以通过setsockopt() 在单个套接字上完全禁用它(但是我不记得是什么选项),但是您可能偶尔会向在连接关闭期间丢失数据包的对等方发送可能不需要的 RST 段。

    至于为什么您只在连接的一侧看到它们,可能是在请求首先关闭连接的一侧。就是它发送第一个 FIN,接收到 FIN+ACK,然后发送最后一个 ACK​​。如果最后一个 ACK​​ 丢失,它将再次收到 FIN+ACK,并且应该重新发送 ACK,而不是 RST。然而,另一方肯定知道当最后一个 ACK​​ 到达时连接已经完全完成,然后就不需要在那个套接字上等待任何其他东西——如果有任何东西到达那个具有相同地址对的主机+ TCP 端口端点作为刚刚关闭的套接字,它应该是一个新的连接请求(在这种情况下可能会打开一个新的连接),或者它是一些 TCP 状态机违规(并且必须用 RST 响应,或者可能一些 ICMP 禁止消息)。

    【讨论】:

    • TIME_WAIT 肯定在第一个关闭的一侧。 TIME_WAIT 的动机不仅仅是缺少 ACK。
    • 帖子已更新为图片,似乎是最后一个 ACK​​ 已发送。另一个问题是:谁负责处理最后一个ACK,是c++ code还是Windows operating system
    • @aj3423 操作系统:更准确地说,是网络协议栈中的 TCP 实现。发送和接收最后一个 ACK​​ 不会阻止 TIME_WAIT。 NB 代码格式化是针对代码的:否则请使用普通引号。
    猜你喜欢
    • 2020-05-02
    • 2016-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-20
    • 1970-01-01
    相关资源
    最近更新 更多