3. TCP 序列号与确认机制:序列号(SEQ)、确认号(ACK)、滑动窗口原理

TCP 的可靠性核心在于其精密的序列号与确认机制。序列号(SEQ)用于标识字节流中的每一个字节,确认号(ACK)则告知发送方已成功接收的数据位置。滑动窗口则在此基础上实现了流量控制与高效传输。理解这三者的协同关系,是排查网络丢包与重传问题的关键。

3.1 序列号(SEQ)与确认号(ACK)

TCP 将应用层数据视为连续的字节流。每个字节在流中都有一个唯一的序号。序列号(SEQ)字段表示当前报文段中第一个字节的序号。确认号(ACK)字段表示期望接收的下一个字节的序号,同时也隐含地确认了该序号之前的所有字节均已成功接收。

核心规则:ACK 号 = 已成功接收的最后一个字节的序号 + 1。例如,收到 SEQ=1001,长度 100 字节的数据,则回复 ACK=1101。
排查要点:在抓包分析中,若发现大量重复的 ACK 号(如连续 3 个相同的 ACK),通常意味着对端未收到期望的报文段,这是触发快速重传的典型信号。

3.1.1 三次握手阶段的 SEQ/ACK 交换

步骤 方向 报文内容 说明
1 客户端 → 服务器 SYN, SEQ=x 客户端初始化序列号 x,请求建立连接
2 服务器 → 客户端 SYN+ACK, SEQ=y, ACK=x+1 服务器确认客户端 SYN,并发送自己的 SYN
3 客户端 → 服务器 ACK, SEQ=x+1, ACK=y+1 客户端确认服务器 SYN,连接建立完成
三次握手 SEQ/ACK 交换流程 客户端 服务器 ① SYN, SEQ=x ② SYN+ACK, SEQ=y, ACK=x+1 ③ ACK, SEQ=x+1, ACK=y+1 SEQ 和 ACK 在握手阶段完成同步 后续数据传输均基于此初始序列号进行偏移计算

3.2 滑动窗口原理

滑动窗口是 TCP 实现流量控制和可靠传输的核心机制。它允许发送方在未收到确认的情况下,连续发送多个报文段,从而充分利用网络带宽。窗口大小由接收方的接收能力(接收缓冲区剩余空间)决定,并通过 TCP 头部的 Window 字段通告给发送方。

3.2.1 发送方窗口结构

发送方维护的窗口被划分为四个区域:

  • 已发送并已确认:最左侧,已安全送达。
  • 已发送但未确认:等待 ACK 的报文段。
  • 允许发送但未发送:窗口内剩余可用空间。
  • 不允许发送:超出窗口范围,必须等待窗口滑动。
常见问题:当接收方处理速度慢于发送方时,接收方会通告较小的窗口(甚至零窗口)。若发送方持续发送,将导致数据在接收缓冲区溢出而被丢弃,进而触发重传。排查时需关注抓包中的 Window 字段变化。
发送方滑动窗口结构 已确认 已发送未确认 可发送 不可发送 左边界(已确认) 右边界(窗口大小) 窗口滑动:收到 ACK 后,左边界右移 新数据进入“可发送”区域,实现连续传输 窗口大小由接收方通告的 Window 字段决定

3.3 SEQ/ACK 与滑动窗口的协同工作

在实际传输中,SEQ、ACK 和滑动窗口三者紧密配合。发送方根据窗口大小连续发送数据,接收方收到后回复 ACK 并更新窗口大小。若发生丢包,接收方会持续发送重复 ACK(DupACK),发送方据此判断丢包并触发重传。

3.3.1 正常传输与丢包场景对比

场景 发送方行为 接收方行为 抓包特征
正常传输 按窗口大小连续发送,收到 ACK 后滑动窗口 按序接收,回复累积 ACK SEQ 连续递增,ACK 稳步增长
单包丢失 收到 3 个重复 ACK 后快速重传丢失报文 缓存后续报文,持续发送丢失报文的 ACK 连续 3 个以上相同 ACK 号,随后出现重传 SEQ
窗口满 停止发送,等待 ACK 释放窗口 通告零窗口或小窗口 Window 字段逐渐减小至 0
SEQ/ACK 与滑动窗口协同:正常 vs 丢包 发送方 接收方 SEQ=1001, Len=100 ACK=1101, Win=4096 SEQ=1101, Len=100 (丢失) SEQ=1201, Len=100 SEQ=1301, Len=100 DupACK=1101 DupACK=1101 快速重传 SEQ=1101 ACK=1401, Win=4096 3 个重复 ACK 触发快速重传,避免超时等待

3.4 排查实践:从抓包中识别 SEQ/ACK 异常

在 Wireshark 或 tcpdump 抓包中,以下现象是排查的重点:

  • ACK 号停滞:长时间未更新,表明接收方未收到新数据。
  • 重复 ACK:连续出现相同 ACK 号,是丢包的直接证据。
  • 窗口大小骤降:接收方处理能力不足,可能导致零窗口探测。
  • SEQ 跳跃:出现非连续的 SEQ 号,通常伴随重传。
排查命令示例:使用 tcpdump 抓取特定端口的 TCP 流量,并过滤 SEQ/ACK 异常。
# 抓取 80 端口流量,显示 SEQ 和 ACK
tcpdump -i eth0 -nn -S port 80

# 过滤重复 ACK(假设目标 IP 为 10.0.0.2)
tcpdump -i eth0 -nn "tcp[13] & 24 == 16" and host 10.0.0.2
专家建议:在 Wireshark 中启用“TCP Analysis Flags”列,可以自动标记出重传、重复 ACK、窗口更新等事件,大幅提升排查效率。