观海听涛
Waiting for you

TCP连接终止与TIME_WAIT状态

26 Mar 2014

TCP连接的断开过程

TCP建立连接需要3个分组,终止一个连接则需要4个分组。过程如下:

  1. 某个应用进程首先调用close,称该端执行主动关闭,该端的TCP于是发送一个FIN分组,表示后面没有数据要再发送了。
  2. 接收到这个FIN的对端执行被动关闭,这个FIN由TCP确认。它的接收也作为一个文件结束符传递给接收端应用程序(放在已排队等候该应用程序接收的任何其他数据之后)。
  3. 一段时间后,接收到这个文件结束符的应用进程调用close关闭它的套接字。这会导致它的TCP也发送一个FIN。
  4. 接收到这个最终FIN的原发端TCP确认这个FIN。

TIME_WAIT状态为什么要存在

TIME_WAIT状态有两个存在的理由

  1. 可靠地实现TCP全双工连接的终止。
  2. 允许老的重复分组在网络中消逝。

对第一个理由的解释:如上图所示,如果执行主动关闭的一端(即最先发出FIN的一端)的最后一个ACK确认丢失,服务器将重新发送它的最终的那个FIN,因此客户端必须维护状态信息,以允许它重新发送最终那个ACK。要是客户端不维护这个信息的话,它将响应一个RST,该分组将被服务器解释成一个错误。如果TCP打算执行所有必要的工作以彻底终止某个连接上两个方向的数据流(即全双工关闭),那么它必须正确处理连接终止序列4个分组中任何一个分组丢失的情况。执行主动关闭的那一端是处于TIME_WAIT状态的那一端:因为可能不得不重传最终那个ACK的就是那一端。

为理解第二个理由,假设在172.16.18.11:1500和172.16.18.13:1200之间有一个TCP连接。现在关闭这个连接,过一段时间后在相同的IP和端口之间建立另一个连接。这里把后一个连接称为前一个连接的化身。TCP必须防止来自某个连接的老的重复分组在该连接已终止后再现,从而被误解成属于同一连接的化身。为做到这一点,TCP将不给处于TIME_WAIT状态的连接发起新的化身。既然TIME_WAIT状态的持续时间是MSL(MSL是任何数据报能够在因特网中存活的最长时间)的2倍,这就足以让某个方向上的分组最多存活MSL秒即被丢弃,另一个方向上的应答最多存活MSL秒也被丢弃。通过这个规则,就可以保证每成功建立一个TCP连接时,来自该连接先前化身的老的重复的分组都已经在网络中消逝了。