![](http://dl2.iteye.com/upload/attachment/0126/1456/b51915ca-778c-31c7-98de-e4decbf91711.png)
TCP 为一个连接定义了 11 种状态,这些状态可使用 netstat 显示,并且 TCP 规则规定如何基于当前状态及在该状态下所接收的分节从一个状态转换到另一种状态。比如,当某个应用进程在 CLOSED 状态下执行主动打开时,TCP 将发送一个 SYN,且新的状态是 SYN_SENT。如果这个 TCP 接着接收到一个带 ACK 的 SYN,它将发送一个 ACK,且新的状态是 ESTABLISHED。这个最终状态是绝大多数数据传送发生的状态。自 ESTABLISHED 状态引出的两个箭头处理连接的终止。如果某个应用进程在接收到一个 FIN 之前调用 close(主动关闭),那就转换到 FIN_WAIT_1 状态。但如果某个应用进程在 ESTABLISHED 状态期间接收到一个 FIN(被动关闭),那就转换到 CLOSE_WAIT 状态。
下图展示一个完整的 TCP 连接所发生的实际分组交换情况,包括连接建立、数据传送和连接终止 3 个阶段,以及每个端点所历经的 TCP 状态。本例中的客户通告一个值为 536 的 MSS(表明该客户只实现了最小重组缓冲区大小),服务器通告一个值为 1460 的 MSS(以太网上 IPv4 的典型值),不同方向上的 MSS 值可以不相同。
![](http://dl2.iteye.com/upload/attachment/0126/1458/3d439966-b11b-3c1e-ac5a-41440c70e816.png)
图中有个 TIME_WAIT 状态,一般执行主动关闭的那端在该状态的持续时间是 2MSL(maximum segment liftime, MSL),即 1 分钟到 4 分钟之间(RFC 1122 建议 MSL 值是 2 分钟,而源自 Berkeley 的实现传统上改用 30 秒)。MSL 是任何 IP 数据报能够在因特网中存活的最长时间。该值是有限的,因为每个数据报都含有一个称为跳限(hop limit)的 8 位字段,其最大值为 255。尽管这是一个跳数限制而非真正的时间限制,不过我们仍然假设:具有最大跳限的分组在网络中存在的时间不可能超过 MSL 秒。TIME_WAIT 状态有两个存在的理由:
1、可靠地实现 TCP 全双工连接的终止。
2、允许老的重复分节在网络中消逝。
第一个理由可假设丢失了上图中的最后一个 ACK 来解释。此时服务器将重新发送它的那个 FIN,因此客户必须维护状态信息,以允许它重发最终那个 ACK,否则它将相应以一个 RST,该分节将被服务器解释成一个错误。若 TCP 要彻底执行全双工关闭,则必须正确处理连接终止序列 4 个分节中的任何一个丢失的情况。本例子也说明了处于 TIME_WAIT 状态的是执行主动关闭的那一端的原因,因为可能不得不重传最终那个 ACK 的就是那一端。
而对于第二个理由,我们可假设打算先正常关闭一个连接,之后再在同一个套接字上重新建立一个连接(后一个连接称为前者的化身(incarnation))。TCP 必须防止来自某个连接的老的重复分组在该连接已终止后再现。为此,TCP 将不给处于 TIME_WAIT 状态的连接发起新的化身。既然 TIME_WAIT 状态的持续时间是 2MSL,那就足以让某个方向上的分组最多存活 MSL 秒即被丢弃,另一个方向上的应答也最多存活 MSL 秒。因此就能保证每成功建立一个 TCP 连接时,来自该连接向前化身的重复分组都已在网络中消逝了(不过有一个例外:如果到达的 SYN 的序列号大于前一个化身的结束序列号,源自 Berkeley 的实现将给当前处于 TIME_WAIT 状态的连接启动新的化身。它要求服务器执行主动关闭,因为接收下一个 SYN 的那一端必须处于 TIME_WAIT 状态)。