TCP 连接管理

三次握手建立连接 · 四次挥手释放连接 · 状态机完整演示

目录

  1. 为什么需要连接管理?
  2. TCP 报文段关键标志位
  3. 三次握手(连接建立)
  4. 为什么是三次而不是两次?
  5. 四次挥手(连接释放)
  6. TIME_WAIT 状态详解
  7. 完整状态机对照表
  8. 总结

1. 为什么需要连接管理?

UDP 是无连接的,发了就走,不管对方收没收到。TCP 在发数据之前要先"建立连接",原因有三:

同步序号(ISN):TCP 用序号来标识每个字节,双方各自选择一个初始序号(Initial Sequence Number),必须在握手时告诉对方,否则后续的确认机制无从建立。

协商参数:最大报文段长度(MSS)、窗口大小、是否支持扩展选项(SACK、时间戳等)都在握手时协商。

验证双向可达:只有通过握手,双方才能确认"我能发到你、你能发到我"这条双向通路是通的。这也是为什么需要三次,不是两次。

应用层(HTTP / FTP / SMTP …) 传输层 — TCP(面向连接,可靠传输) 端口号 seq/ack

2. TCP 报文段关键标志位

TCP 首部中有 6 个控制标志位,连接管理主要用到其中三个:

SYN(Synchronize):同步序号,请求建立连接时置 1。携带 SYN 的报文段会消耗一个序号(即使没有数据载荷)。

ACK(Acknowledgment):确认有效位。ACK=1 时确认号字段才有意义。连接建立后,所有报文段的 ACK 都为 1。

FIN(Finish):请求释放连接。与 SYN 一样,FIN 也会消耗一个序号。

URG ACK PSH RST SYN FIN 紧急 确认 推送 复位 同步 结束

注意:SYN=1 的报文段不能携带数据,但要消耗一个序号;FIN=1 的报文段也消耗一个序号。这两点在计算题中非常重要。

3. 三次握手(连接建立)

客户端主动发起连接,服务器处于监听状态(LISTEN)。三次握手的本质是双方各自告知序号,并且都得到确认

客户端 CLOSED 服务器 LISTEN SYN seq=x 第 ① 次握手 SYN+ACK seq=y ack=x+1 第 ② 次握手 ACK seq=x+1 ack=y+1 第 ③ 次握手(可携带数据)
点击"下一步"开始演示三次握手过程...
1 / 4

也可使用键盘 翻步

三次握手的完整过程:

1
客户端发送 SYN:选择初始序号 x(ISN),发送 SYN seq=x。客户端进入 SYN_SENT 状态。
2
服务器回复 SYN+ACK:确认客户端的 SYN(ack=x+1),同时发送自己的 SYN(seq=y)。服务器进入 SYN_RCVD 状态。
3
客户端发送 ACK:确认服务器的 SYN(ack=y+1)。第三次握手可以携带数据。双方进入 ESTABLISHED 状态,连接建立。

注意 ISN(初始序号)的选择:ISN 并非从 0 开始,而是根据系统时钟选取一个随机值,目的是防止旧连接的延迟报文被误认为新连接的数据。

4. 为什么是三次而不是两次?

这是 408 的经典考题。核心原因:两次握手只能让服务器确认客户端能发、服务器能收;但客户端无法确认服务器能发、客户端能收。

更本质的原因是:TCP 是全双工的,双方都需要同步序号,且都需要得到确认。总共需要 4 次(客户端 SYN + 服务器 ACK + 服务器 SYN + 客户端 ACK),但服务器可以把 ACK 和 SYN 合并成一个报文,因此是三次。

如果只有两次握手,还会有一个具体问题:历史失效连接请求。客户端发了一个 SYN,在网络中滞留很久后到达服务器,服务器以为是新连接,发出 SYN+ACK 后就进入 ESTABLISHED,开始等待数据——但客户端早已不再理这个连接了,服务器的资源就白白浪费了。三次握手中,客户端不会回复 ACK,服务器就不会进入 ESTABLISHED。

✓ 三次握手(正确)

客户端确认:我能发、能收。
服务器确认:我能发、能收。
双向通路全部验证。

✗ 两次握手(不够)

服务器发出 SYN+ACK 后即 ESTABLISHED,但不知道客户端是否收到。历史失效 SYN 会导致资源浪费。

5. 四次挥手(连接释放)

连接释放需要四次,原因是 TCP 是全双工的,两个方向的数据流要分别关闭。主动关闭方(通常是客户端)先关自己到对方的方向,被动关闭方可能还有数据要发,等发完再关另一方向。

客户端 ESTABLISHED 服务器 ESTABLISHED FIN seq=u 第 ① 次挥手 ACK ack=u+1 第 ② 次挥手 ↑ 半关闭状态,服务器可继续发数据 FIN seq=v ack=u+1 第 ③ 次挥手 服务器数据发送完毕 ACK ack=v+1 第 ④ 次挥手 客户端进入 TIME_WAIT
点击"下一步"开始演示四次挥手过程...
1 / 5

也可使用键盘 翻步

四次挥手的关键细节:

1
客户端发 FINseq=u):表示客户端没有数据要发了,进入 FIN_WAIT_1
2
服务器回 ACK:确认收到 FIN,进入 CLOSE_WAIT。此时连接处于半关闭状态——客户端不再发数据,但服务器还可以继续发。客户端收到 ACK 后进入 FIN_WAIT_2
3
服务器发 FINseq=v):服务器数据发完,发出自己的 FIN,进入 LAST_ACK
4
客户端回 ACK:进入 TIME_WAIT,等待 2MSL 后再关闭。服务器收到 ACK 后立即进入 CLOSED

6. TIME_WAIT 状态详解

TIME_WAIT 是四次挥手中最容易考到的知识点。客户端发出最后一个 ACK 后,不会立即关闭,而是等待 2MSL(Maximum Segment Lifetime,报文最大生存时间)

原因有两个:

原因一:确保最后一个 ACK 能到达服务器。如果服务器没有收到最后的 ACK,会重传 FIN。客户端等待 2MSL,意味着能收到这个重传的 FIN 并再次发 ACK。如果客户端立即关闭,则无法处理重传,服务器就会一直处于 LAST_ACK 状态。

原因二:防止"旧连接的残留报文"污染新连接。等待 2MSL 能确保本次连接所有报文都在网络中消失,下一个用同样四元组(源IP/端口+目标IP/端口)建立的连接不会收到旧的迷途报文。

客户端发出 ACK 等待 1 MSL 等待 1 MSL ACK 在途 + 服务器可能重传 FIN 旧报文在网络中彻底消失 CLOSED
TIME_WAIT 的 2MSL 定时器在 客户端 启动,不是服务器。服务器收到最后的 ACK 后立即 CLOSED。TIME_WAIT 发生在主动关闭的一方。

7. 完整状态机对照表

408 常考状态转移,尤其是三次握手和四次挥手各阶段双方的状态。

阶段事件客户端状态服务器状态
握手前CLOSEDLISTEN
握手①客户端发 SYNSYN_SENTLISTEN
握手②服务器发 SYN+ACKSYN_SENTSYN_RCVD
握手③客户端发 ACKESTABLISHEDESTABLISHED
挥手①客户端发 FINFIN_WAIT_1ESTABLISHED
挥手②服务器发 ACKFIN_WAIT_2CLOSE_WAIT
挥手③服务器发 FINFIN_WAIT_2LAST_ACK
挥手④客户端发 ACKTIME_WAITCLOSED
2MSL后定时器超时CLOSEDCLOSED

易错点:握手③之后服务器才进入 ESTABLISHED(不是②之后);TIME_WAIT 只在主动关闭方(客户端)出现,不在服务器。

8. 总结

三次握手 = 双方各同步一个序号,都得到确认,最少需要三次。两次不够(不能验证双向可达,无法防止历史失效 SYN);更多次没意义。

四次挥手 = 全双工的两条数据流各自独立关闭。②③之间存在半关闭状态,服务器可以继续发数据,这是与握手的本质区别。

TIME_WAIT = 主动关闭方的最后一道保险,等待 2MSL 的目的是确保最后 ACK 送达 + 清空网络中的旧报文。

核心记忆:握手确认序号(SYN消耗序号),挥手关闭数据流(FIN消耗序号),TIME_WAIT在主动关闭方等2MSL。