学习Wireshark时遇到TCP SEQ与ACK不匹配的技术咨询
嘿,这个问题我之前排查TCP报文时也碰到过,一开始完全摸不着头脑,来帮你拆解下~
先把你给出的SEQ/ACK数据整理清楚(方便后续分析):
1 1;2897 8689;5793 13033 <-- 8689 14481;11585 14481
这里的<--应该是表示反向的TCP流(比如服务器→客户端,或者反过来)对吧?结合你说的“两次ACK差值等于1加上半个数据包大小”,大概率是这几种情况导致的:
1. TCP分段导致非整包ACK递增
TCP的ACK序号是严格按照实际收到的字节数来递增的,根本不需要匹配所谓的“完整数据包大小”(你说的完整包可能指MTU对应的最大段大小MSS)。如果发送方因为某种原因把应用层数据拆分成了非MSS大小的分段——比如最后一段数据不足MSS,或者中途触发了路径MTU发现机制拆分数据包——那ACK的增量就会是这个分段的实际长度。
比如假设你的MSS是5792字节(半个就是2896),如果某次收到的分段是2897字节(2896+1),那ACK就会比上一次多2897,刚好对应你说的“1加上半个数据包大小”。
2. 捎带ACK(Piggybacking)的干扰
有时候ACK报文本身会携带数据(也就是把ACK和自己要发送的数据打包在同一个报文里,俗称“捎带”),这时候你看到的SEQ是发送方的当前发送序号(会加上自身携带的数据长度),而ACK是确认对方之前发送的字节数。两者分别对应两个方向的数据流,完全独立,很容易让你误以为SEQ和ACK的变化不匹配。
比如你数据里的<-- 8689 14481,这个反向报文的SEQ=8689是它自己的发送起始序号,ACK=14481是确认对方已经发送到了14480字节(因为ACK是期望收到的下一个字节的序号),这个ACK的增量就是实际收到的分段大小。
3. Wireshark相对序号的“迷惑性”
默认情况下,Wireshark会显示相对序号(把初始SEQ设为1,后续序号都是相对于初始值的偏移),而非绝对序号。如果你没注意到这个设置,很可能在计算差值时出错。你可以去Preferences -> Protocols -> TCP里看看是否勾选了Relative Sequence Numbers,如果是的话,切换成绝对序号再重新计算,说不定就能匹配上你的预期了。
总结一下:TCP的ACK只认实际收到的字节数,不管分段大小是否“完整”;捎带ACK和相对序号显示也容易造成误解,先排查这几个点应该就能找到原因啦~
内容的提问来源于stack exchange,提问作者Pareidolia

