TCP 三次握手与四次挥手详解

1. 引言

TCP(Transmission Control Protocol,传输控制协议)是互联网中最核心的传输层协议之一,它为应用层提供可靠、面向连接的字节流服务。在 TCP 建立连接和断开连接的过程中,三次握手与四次挥手是两个最基础也最重要的机制。理解这两个过程,是深入掌握网络编程、排查连接异常的前提。

2. TCP 报文段中的关键标志位

在讲解握手与挥手之前,先了解 TCP 报文段头部中几个关键标志位,它们是整个流程的核心。

  • SYN(Synchronize):同步标志,用于建立连接时同步序列号。
  • ACK(Acknowledgment):确认标志,表示确认号有效,用于确认收到对方的数据。
  • FIN(Finish):结束标志,表示发送方数据已发送完毕,请求断开连接。
  • SEQ(Sequence Number):序列号,表示本报文段第一个字节的序号。
  • ACK Number(确认号):表示期望收到对方下一个字节的序号。

此外,TCP 连接是全双工的,即数据可以在两个方向上独立传输,因此连接建立和断开都需要在两个方向上分别确认。

3. 三次握手:建立连接

3.1 为什么需要三次握手

三次握手的核心目的有三个:

  • 确认双方的收发能力:确保客户端和服务端都能正确发送和接收数据。
  • 同步双方的初始序列号:为后续可靠传输奠定基础。
  • 防止历史失效连接请求:避免因网络延迟导致旧连接请求误建立新连接。

3.2 三次握手的具体过程

假设客户端为 A,服务端为 B,整个过程如下:

  1. 第一次握手(客户端发送 SYN):客户端向服务端发送一个 SYN 报文段,其中 SYN=1,并携带一个初始序列号 seq=x。此时客户端进入 SYN_SENT(同步已发送)状态。
  2. 第二次握手(服务端回复 SYN+ACK):服务端收到 SYN 报文后,如果同意建立连接,则回复一个 SYN+ACK 报文段,其中 SYN=1、ACK=1,确认号 ack=x+1,并携带自己的初始序列号 seq=y。此时服务端进入 SYN_RCVD(同步已接收)状态。
  3. 第三次握手(客户端回复 ACK):客户端收到 SYN+ACK 报文后,再向服务端发送一个 ACK 报文段,其中 ACK=1,确认号 ack=y+1,序列号 seq=x+1。此时客户端进入 ESTABLISHED(已建立连接)状态;服务端收到该 ACK 后也进入 ESTABLISHED 状态,连接正式建立。

3.3 三次握手的图示

3.4 为什么不是两次或四次

如果只有两次握手,服务端无法确认客户端是否收到了自己的 SYN+ACK 报文,也无法防止历史失效连接请求导致的资源浪费。而三次握手已经能够可靠地同步双方序列号并确认收发能力,四次则没有必要,反而增加延迟。因此三次握手是可靠性与效率之间的最佳平衡。

4. 四次挥手:断开连接

4.1 为什么需要四次挥手

由于 TCP 连接是全双工的,每个方向都必须独立关闭。当一方完成数据发送后,可以发送 FIN 报文关闭该方向的传输,但此时仍可以接收对方的数据。因此断开连接需要四次交互,分别关闭两个方向的数据通道。

4.2 四次挥手的具体过程

假设客户端主动发起断开连接,整个过程如下:

  1. 第一次挥手(客户端发送 FIN):客户端发送 FIN 报文段,其中 FIN=1,序列号 seq=u,表示客户端数据已发送完毕,请求断开连接。客户端进入 FIN_WAIT_1(终止等待 1)状态。
  2. 第二次挥手(服务端回复 ACK):服务端收到 FIN 报文后,回复 ACK 报文段,其中 ACK=1,确认号 ack=u+1,序列号 seq=v。此时服务端进入 CLOSE_WAIT(关闭等待)状态,客户端收到 ACK 后进入 FIN_WAIT_2(终止等待 2)状态。此时服务端仍可能继续发送数据。
  3. 第三次挥手(服务端发送 FIN):当服务端的数据也发送完毕后,服务端发送 FIN 报文段,其中 FIN=1,ACK=1,序列号 seq=w,确认号 ack=u+1。服务端进入 LAST_ACK(最后确认)状态。
  4. 第四次挥手(客户端回复 ACK):客户端收到 FIN 报文后,回复 ACK 报文段,其中 ACK=1,确认号 ack=w+1,序列号 seq=u+1。客户端进入 TIME_WAIT(时间等待)状态,服务端收到 ACK 后进入 CLOSED(关闭)状态。客户端在等待 2MSL(最大报文段生存时间)后进入 CLOSED 状态,连接彻底关闭。

4.3 四次挥手的图示

4.4 为什么客户端要等待 2MSL

客户端在发送最后一个 ACK 后进入 TIME_WAIT 状态,并等待 2MSL 时间,原因主要有两点:

  • 确保最后一个 ACK 能到达服务端:如果该 ACK 丢失,服务端会重发 FIN,客户端需要能够再次回复 ACK。若客户端立即关闭,则无法响应重发的 FIN。
  • 让旧报文在网络中自然消失:等待 2MSL 可以确保本次连接的所有报文段都在网络中消失,避免影响后续使用相同端口的新连接。

5. 常见问题与面试要点

5.1 三次握手中可以携带数据吗

第一次和第二次握手不能携带数据,因为此时连接尚未建立,若携带数据可能造成资源浪费和安全隐患。第三次握手时连接已基本建立,可以携带数据。

5.2 为什么挥手需要四次而握手只需要三次

握手时,服务端的 SYN 和 ACK 可以在同一个报文段中发送,因为服务端在收到 SYN 后可以立即同步自己的序列号并确认客户端的序列号。而挥手时,服务端收到 FIN 后可能仍有数据需要发送,因此 ACK 和 FIN 不能合并,需要分两次发送,所以挥手需要四次。

5.3 大量 TIME_WAIT 状态如何处理

在高并发场景下,主动关闭连接的一方可能出现大量 TIME_WAIT 状态的连接,占用端口资源。常见的优化手段包括:开启 TCP 时间戳选项、调整 MSL 值、复用 TIME_WAIT 连接(如开启 tcp_tw_reuse)等,但需结合具体业务场景谨慎使用。

6. 总结

三次握手通过 SYN、SYN+ACK、ACK 三次交互,可靠地建立了全双工连接并同步了双方序列号;四次挥手则通过 FIN、ACK、FIN、ACK 四次交互,分别关闭两个方向的数据通道,确保数据完整传输后安全断开。理解这两个过程,不仅有助于掌握 TCP 协议的本质,也是排查网络故障、优化服务性能的重要基础。

相关推荐
新时代牛马1 小时前
实时 Linux:PREEMPT_RT、延迟来源与观测
linux·运维·服务器
微露清风2 小时前
# Linux 进程全景:从 PCB 到 O(1) 调度队列
linux·服务器
anxiao_m2 小时前
2026企业AI数字孪生选型攻略,不同场景对应不同解决方案
大数据·网络·数据库
xiaoye-duck3 小时前
《Linux 网络编程》深入理解 TCP 协议(二):序号、确认应答与流量控制机制详解
linux·网络·tcp
北京盛世宏博3 小时前
物联网传感器通信协议:帧字段规划、CRC 校验、异常包过滤方案
网络·物联网·php
楚疏笃3 小时前
linux下给OpenCloudOS根目录扩容
linux·运维·服务器
dog2503 小时前
网络的时延抖动
linux·运维·网络
devpotato3 小时前
高可用系统如何定义可用性
服务器·网络·可用性测试
程序员-Benothing3 小时前
Linux 软件包管理:yum / apt / dnf 命令使用全解析
linux·运维·服务器