序列号与确认号是什么
TCP 把数据看成字节流,每个字节都有一个序号:报文头里的序号表示本报文首个字节的位置,确认号表示「这个位置之前的字节我都连续收到了」。初始序号 ISN 不是从 0 开始,而是随机生成以抵抗连接伪造与旧报文串扰(RFC 6528)。接收方遇到乱序段会先放入缓冲,等缺口被重传补齐后再按序交付给应用。
基本信息
| 序号 | 32 位,本报文首字节在字节流中的位置 |
|---|---|
| 确认号 | 32 位,累积确认,表示期望的下一个字节 |
| ISN | 连接建立时随机生成,非固定 0 |
| 选择性确认 | SACK 选项可额外声明已收到的乱序区间 |
| 规范 | RFC 9293 §3.3、RFC 6528 |
| 抓包显示 | tcpdump 默认相对序号,-S 显示绝对序号 |
典型使用场景
- 分析重传:同一序号重复出现说明该段未被确认
- 识别乱序:序号跳跃但都在窗口范围内,通常是路径多链路负载分担造成
- 判断丢包位置:连续多个重复确认(duplicate ACK)提示对端在催缺口数据
- 验证 SACK 是否生效:抓包看选项区是否有 SACK 块,影响重传效率
- 对账抓包与应用日志:用绝对序号才能与内核日志对上
抓包观察序号与确认号
抓包观察序号与确认号
tcpdump -nn -S 'tcp port 8080' -c 6 # -S:显示绝对序号,便于对账
tcpdump -nn -v 'tcp port 8080' -c 2 | grep -i -E 'seq|ack'
tcpdump -nn -v 'tcp port 8080' -c 20 | grep -c 'seq' # 粗看是否有重复序号
ss -ti '( dport = :8080 )' # 内核侧看重传与 rtt 统计现象与归因
| 抓包现象 | 含义 | 排查方向 |
|---|---|---|
| 同一 seq 多次出现 | 该段被重传,说明未收到确认 | 查路径丢包与对端接收缓存的状况 |
| 相同 ack 连续出现多次 | 对端在催缺口数据 | 定位缺口与丢包点 |
| seq 跳跃但被后续 ack 覆盖 | 乱序,非丢包 | 多为多路径或链路聚合导致 |
| ack 长时间不前进 | 对端应用不读取数据或卡死 | 看接收窗口是否降到 0 |
| 窗口内出现空洞且无重传 | SACK 生效,选择性补发 | 属于正常优化行为 |
Wireshark 提供现成过滤器:tcp.analysis.retransmission 列重传、tcp.analysis.out_of_order 列乱序,比手工比对序号快得多;分析前记得把相对序号关掉。
SACK(选择性确认)让接收方可以报告「缺哪一段」,发送方只需重传缺口而不是把缺口之后的数据全部重发,在高带宽高延迟链路上对吞吐影响很大。