序列号和确认号不匹配

Sequence number and acknowledgement number do not match

最近在学习wireshark。在检查 TCP 段时,我看到了一个奇怪的情况,至少对我来说是这样。存在不匹配的 SEQ、ACK 编号。然后我意识到两个 ACK​​ 之间的区别与 1 和一半的包大小相同。然而,据我所知,ACK 只会随着整个数据包的大小而增长。那么这里发生了什么?

SEQ        ACK
1          1
2897       8689
5793       13033 <--
8689       14481
11585
14481

好吧,这里没什么好说的,但我猜你正在捕获发送大数据包的机器上的数据包,即具有 2896 字节 TCP 有效负载的数据包。因此,您看到数据包 before 它们是 IP-fragmented 并且实际上是通过网络传输出去的。

但是您不能只将 2896 字节的数据发送到线路上;以太网链路通常强加 1500 字节的 MTU(最大传输单元),当您考虑 IP 和 TCP header 开销时,您通常会得到 1460 字节的可用负载或 MSS(最大段大小)。在您的情况下,您似乎只获得了 1448 字节的可用 MSS,这很可能是由于添加了一个或多个 IP and/or TCP header 选项。

在任何情况下,2896 字节的有效负载将被分成 2 个 IP 片段,每个片段包含 1448 字节的 TCP 有效负载。我很确定您看到的是接收方在收到 1 个完整段加上来自下一个段的 1 个 IP 片段后的 ACK。

之前的ACK号是8689,8689+2896=11585,现在加上数据段的1/2(2896/2=1448),就是11585+1448=13033,这就是你的ACK号重新看到。现在加上另外1/2,得到13033 + 1448 = 14481,也就是下一个数据包的ACK号。

我希望这是有道理的?

要深入了解本地数据包捕获的缺点,我会引导您阅读 Jasper Bongertz 的 well-written 博客,标题为 "The drawbacks of local packet captures"

由于我没有评论 Christopher Maynard 的答案的声誉,所以我在这里评论它。

正如 Christopher 正确指出的那样,MTU(最大传输单元)是标准以太网网络的 1500 字节。然而,制作 1460 字节(1500 字节 - 20 字节 IP Header - 20 字节 TCP Header,忽略可能的 TCP 选项)TCP 段会给网络堆栈带来高负载,因为每个段都必须单独处理。

例如,如果我要传输 1Mb(等于 1024*1024Bytes = 1048576Bytes)的数据,将导致 1Mb/1460Bytes = 719 段。与 1Mb/65525Bytes(理论上的最大 TCP 段大小)= 16 个段相反。由于内核中的开销主要与 segment/packet 大小无关,因此小段需要更多处理。

为了抵消这一事实,开发了 TCP 分段卸载 (TSO)。 TSO 允许内核制作最大大小的 TCP 段,NIC(网络接口卡)使用硬件加速将这些段拆分为 1460 字节的单独 TCP 段。所以不需要IP分片。