Linux 网络

 

TTIME_WAIT 状态原理

通信双方建立 TCP 连接后,主动关闭连接的一方就会进入 TIME_WAIT 状态。

客户端主动关闭连接时,会发送最后一个 ack 后,然后会进 入TIME_WAIT 状态,再停留 2 个 MSL 时间(后面解释),进入 CLOSED 状态。

TCP/IP 协议就是这样设计的,是不可避免的。主要有两个原因:

1)可靠地实现 TCP 全双工连接的终止

TCP 协议在关闭连接的 4 次挥手过程中,最终的 ACK 是由主动关闭连接的一端(后面统称 A 端)发出的,如果这个 ACK 丢失,对方(后面统称 B 端)将重发出最终的 FIN,因此 A 端必须维护状态信息(TIME_WAIT)允许它重发最终的 ACK。如果 A 端不维持 TIME_WAIT 状态,而是处于 CLOSED 状态,那么 A 端将响应 RST 分节,B 端收到后将此分节解释成一个错误(在 java 中会抛出 connection reset 的 SocketException)。

因而,要实现 TCP 全双工连接的正常终止,必须处理终止过程中 4 个分节任何一个分节的丢失情况,主动关闭连接的 A 端必须维持 TIME_WAIT 状态 。

2)允许老的重复分节在网络中消逝

TCP 分节可能由于路由器异常而“迷途”,在迷途期间,TCP 发送端可能因确认超时而重发这个分节,迷途的分节在路由器修复后也会被送到最终目的地,这个迟到的迷途分节到达时可能会引起问题。在关闭“前一个连接”之后,马上又重新建立起一个相同的 IP 和端口之间的“新连接”,“前一个连接”的迷途重复分组在“前一个连接”终止后到达,而被“新连接”收到了。为了避免这个情况,TCP 协议不允许处于 TIME_WAIT 状态的连接启动一个新的可用连接,因为 TIME_WAIT 状态持续 2MSL,就可以保证当成功建立一个新 TCP 连接的时候,来自旧连接重复分组已经在网络中消逝。

MSL 就是 maximum segment lifetime (最大分节生命期),这是一个 IP 数据包能在互联网上生存的最长时间,超过这个时间 IP 数据包将在网络中消失 。MSL 在 RFC 1122 上建议是 2 分钟,而源自 berkeley 的 TCP 实现传统上使用 30 秒。

以上摘自网络。

设置大一些为了让网络更可靠,能够安全的关闭连接以及让迷途的 tcp 分节不影响新的连接通讯。

如果设置的小比如 200,假如系统有高频的连接创建断开的操作,会迅速增加 TIME_WAIT 状态的连接,但是实际上只能容纳 200 个 TIME_WAIT 状态的连接,导致很多连接断开后没等到 2MSL 就消逝了,那么有可能会导致连接断开异常以及 tcp 通讯异常。

net.ipv4.tcp_tw_recycle = 0

这个文档有注释。为了防止 nat 网络里的客户端连接服务端超时。

如果服务器开了 tcp_tw_recycle 和 tcp_timestamps,那么会导致 nat 网络里的客户端连接以及通讯超时。

所以要关闭其中的一个。关闭 tcp_timestamps 也可以。

EOF