TCP 连接管理:三次握手与四次挥手

TCP 是面向连接的可靠传输协议,连接建立与释放分别靠"三次握手"与"四次挥手"完成。这两张时序图是网络面试出现频率最高的考题,要求既能画图,又能解释"为什么是三次、为什么是四次"。

报文段关键字段

  • 序号 seq:本报文段数据第一个字节的编号,用于排序与去重。
  • 确认号 ack:期望收到的下一个序号,含义是"此前的字节我都收到了"。
  • 标志位:SYN 建立连接、ACK 确认、FIN 关闭连接、RST 重置、PSH 立即交付。

三次握手:建立连接

TCP 三次握手四次挥手 目的是同步双方的初始序号,并确认双方收发能力都正常:

客户端                                    服务器
  │ 1. SYN=1, seq=x                      │
  │────────────────────────────────────>│ 服务器: SYN_RCVD
  │ 2. SYN=1, ACK=1, seq=y, ack=x+1      │
  │<────────────────────────────────────│
  │ 3. ACK=1, seq=x+1, ack=y+1           │
  │────────────────────────────────────>│ 服务器: ESTABLISHED
  │ (客户端收到后进入 ESTABLISHED)          │

为什么不能只握两次? 防止"已失效的连接请求"突然到达服务器:若第一次握手的请求因网络滞留后到达,服务器会误以为客户端要连接而白白建立空连接、浪费资源。第三次握手让服务器确认客户端确实想连,从而规避。

四次挥手:关闭连接

TCP 是全双工的,每一方向都要单独关闭,因此需要四次:

客户端                                    服务器
  │ 1. FIN=1, seq=u   (客户端不再发数据)    │
  │────────────────────────────────────>│
  │ 2. ACK=1, ack=u+1                   │
  │<────────────────────────────────────│ 服务器继续发送剩余数据
  │ 3. FIN=1, seq=w   (服务器数据也发完)    │
  │<────────────────────────────────────│
  │ 4. ACK=1, ack=w+1                   │
  │────────────────────────────────────>│ 服务器: CLOSED
  │ 客户端等待 2MSL 后关闭                  │

为什么挥手要四次? 被动关闭方收到 FIN 时可能还有数据要发送,不能把"确认"与"关闭"合并成一次,必须拆成 ACK 与 FIN 两步,故比握手多一次。

TIME_WAIT 的意义

主动关闭的一方在发出最后一个 ACK 后,要等待 2MSL(两倍最大报文段生存时间)才彻底关闭:

  • 保证最后一个 ACK 若丢失,能有机会重发;
  • 让本连接迟到的旧报文在网络中消亡,避免污染后续新连接。

运维中服务端出现大量 TIME_WAIT,常见于短连接频繁建立关闭的场景。

连接状态速查

状态所处阶段
LISTEN服务端在端口上等待连接
SYN_SENT / SYN_RCVD三次握手进行中
ESTABLISHED连接已建立,可传输数据
FIN_WAIT_1 / FIN_WAIT_2主动关闭方挥手中
CLOSE_WAIT被动方等应用调用 close()
TIME_WAIT主动方等待 2MSL 后关闭

实战提示:netstat 看到大量 CLOSE_WAIT,通常说明对方关闭连接后,本端应用没有正确执行 close(),多半是代码漏关了连接或流未读完。

小结:三次握手同步序号并验证双向通道,四次挥手因全双工半关闭而多一拍。画熟两张时序图,讲清"为何三次/四次"与 TIME_WAIT 的作用,TCP 连接管理这道大题即可从容作答。

笔记加载中…