3. TCP三次握手原理:SYN、SYN-ACK、ACK标志位详解与状态转换图

TCP三次握手是面向连接通信的基石,它确保通信双方在数据传输前完成序列号同步、窗口协商与资源预留。本节将深入解析SYN、SYN-ACK、ACK三个控制标志位的作用,并通过状态转换图展示连接建立的完整过程。

3.1 三次握手流程与标志位详解

三次握手由客户端主动发起,服务端被动响应,共交换三个报文段。每个报文段携带特定的TCP控制标志位,这些标志位位于TCP首部的Flags字段中。

步骤 方向 报文类型 标志位 核心作用
第1次 Client → Server SYN报文 SYN=1, ACK=0 客户端请求建立连接,携带初始序列号ISN(c)
第2次 Server → Client SYN-ACK报文 SYN=1, ACK=1 服务端确认收到SYN,同时请求建立连接,携带ISN(s)和确认号
第3次 Client → Server ACK报文 SYN=0, ACK=1 客户端确认收到SYN-ACK,连接建立完成,可携带数据
关键概念:SYN标志位用于同步序列号,ACK标志位用于确认收到数据。三次握手中,前两次报文必须设置SYN,第三次报文必须设置ACK。只有第三次握手完成后,双方才能开始传输应用数据。

3.2 序列号与确认号机制

三次握手的核心是交换初始序列号(ISN)并建立确认机制。序列号用于标识字节流中的位置,确认号表示期望收到的下一个字节序号。

  • 第一次握手:客户端发送SYN报文,序列号 seq = x(ISN(c)),不携带数据,消耗一个序列号。
  • 第二次握手:服务端发送SYN-ACK报文,序列号 seq = y(ISN(s)),确认号 ack = x+1,表示已收到客户端的SYN。
  • 第三次握手:客户端发送ACK报文,序列号 seq = x+1,确认号 ack = y+1,表示已收到服务端的SYN-ACK。
验证要点:在抓包测试中,检查第三次握手的确认号是否为第二次握手的序列号加1,这是判断握手是否正确的关键指标。

3.3 状态转换图

TCP连接建立过程中,客户端和服务端各自经历一系列状态变化。下图展示了三次握手对应的完整状态转换路径。

TCP三次握手状态转换图 CLOSED SYN_SENT ESTABLISHED CLOSED LISTEN SYN_RCVD ESTABLISHED 主动打开 被动打开 ① SYN (seq=x) 收到SYN ② SYN-ACK (seq=y, ack=x+1) 收到SYN-ACK ③ ACK (seq=x+1, ack=y+1) 收到ACK 说明:客户端主动发起连接,服务端被动监听。三次握手完成后双方进入ESTABLISHED状态。 半连接队列(SYN Queue)在服务端收到SYN后创建,全连接队列(Accept Queue)在收到ACK后创建。

3.4 半连接队列与全连接队列

服务端在三次握手过程中维护两个关键队列,用于管理未完成和已完成连接的请求。

队列名称 创建时机 状态 存储内容 溢出后果
半连接队列(SYN Queue) 服务端收到SYN后 SYN_RCVD 未完成三次握手的连接请求 SYN Flood攻击、连接超时
全连接队列(Accept Queue) 服务端收到ACK后 ESTABLISHED 已完成三次握手的连接 应用层accept()无法及时处理
测试验证注意:在压力测试中,如果服务端出现大量SYN_RCVD状态连接,说明半连接队列可能已满,需要检查是否遭受SYN Flood攻击或调整tcp_max_syn_backlog内核参数。如果出现大量ESTABLISHED状态但应用层连接数不增长,则需排查全连接队列溢出问题。

3.5 三次握手的抓包验证方法

使用Wireshark或tcpdump抓取三次握手报文时,应关注以下关键字段:

# 使用tcpdump抓取三次握手报文
sudo tcpdump -i eth0 -nn 'tcp port 80 and (tcp[tcpflags] & (tcp-syn|tcp-ack) != 0)'

# 典型输出示例(三次握手)
# 1. 客户端发送SYN
# 10:00:00.001 IP 192.168.1.100.54321 > 192.168.1.1.80: Flags [S], seq 1000, ...
# 2. 服务端回复SYN-ACK
# 10:00:00.002 IP 192.168.1.1.80 > 192.168.1.100.54321: Flags [S.], seq 2000, ack 1001, ...
# 3. 客户端发送ACK
# 10:00:00.003 IP 192.168.1.100.54321 > 192.168.1.1.80: Flags [.], ack 2001, ...
验证检查清单:
  • 第一次握手:SYN标志位为1,ACK标志位为0,序列号为客户端ISN。
  • 第二次握手:SYN和ACK标志位均为1,确认号为客户端ISN+1,序列号为服务端ISN。
  • 第三次握手:ACK标志位为1,SYN标志位为0,确认号为服务端ISN+1。
  • 三次握手完成后,双方序列号应保持同步,后续数据报文从ISN+1开始编号。

3.6 常见异常场景分析

异常场景 现象 可能原因 排查方向
第一次握手无响应 客户端反复重传SYN,最终超时 服务端未启动、防火墙拦截、路由不可达 检查服务端端口监听状态、防火墙规则
第二次握手丢失 客户端收到SYN-ACK后无响应 客户端防火墙拦截、客户端资源耗尽 检查客户端SYN_SENT状态连接数
第三次握手丢失 服务端处于SYN_RCVD状态,重传SYN-ACK 网络丢包、客户端未收到SYN-ACK 检查服务端半连接队列、网络延迟
SYN Flood攻击 大量SYN_RCVD状态连接,半连接队列满 攻击者伪造源IP发送大量SYN 启用SYN Cookie、限制SYN速率
实战建议:在测试环境中,使用ss -tna命令观察连接状态变化。执行三次握手测试时,应能观察到客户端状态从SYN_SENT快速变为ESTABLISHED,服务端状态从LISTEN经过SYN_RCVD最终变为ESTABLISHED。如果某个状态停留时间过长,说明对应步骤存在问题。