2

我知道在发送 ip 消息时,be 和我的数据包目的地之间的网络路径中的每一跳都会检查下一跳的 MTU 是否大于我发送的数据包的大小。如果是这样,数据包将被分片,两个数据包将分别发送到下一跳,仅在目的地(或者,在某些情况下,在遇到的第一个 NAT 路由器)重新组合。据我了解,这件事可能很糟糕,但我真的不明白为什么。

  • 我知道如果连接倾向于丢弃很多数据包,丢失一个片段意味着我必须重新发送整个数据包(这实际上是我自己想出的唯一事情)
  • 是否有可能我的数据包不会被分段而不是被丢弃?
  • 如何识别数据包碎片?我可以 100% 确定它们会正确重新组装吗?例如,如果我几乎同时向同一个目的地发送两个相同长度的 ip 数据包,那么两者的片段交换的可能性有多大,例如 AAA、BBB 重新组合成 ABA、BAB?

原则上,如果数据包没有被丢弃并且片段被正确重组,那么实际上使用数据包分段似乎是一个好主意,可以节省本地带宽并避免发送越来越多的标头而不仅仅是一个大数据包。

谢谢

4

2 回答 2

7

IP 分片可能会导致几个问题:

1)应用层损失增加

正如您所提到的,如果丢弃单个片段,则整个第 4 层数据包将丢失。因此,对于随机丢包率较小的网络,应用层丢包率会增加大约等于每个第 4 层数据包的分片数量的因子。

2) 并非所有网络都处理碎片数据包

某些系统,例如 Google 的 Compute Engine,不会重新组装碎片数据包。

3) 碎片化会导致重新排序

当路由器将流量拆分为并行路径时,它们可能会尝试将来自同一流的数据包保留在单个路径上。因为只有第一个片段具有 UDP/TCP 端口号等第 4 层信息,后续片段可能会沿着不同的路径路由,从而延迟第 4 层数据包的组装并导致重新排序。

4) 碎片化会导致难以调试的混乱行为

例如,如果您将两个 UDP 流(A 和 B)从一个源发送到运行 Linux 的目标,则目标可能会丢弃来自其中一个流的数据包。这是因为默认情况下,如果从同一源接收到超过 64 个其他片段,Linux 会“超时”片段队列。如果流 A 的数据速率比流 B 高得多,则流 A 的 64 个片段可能会到达流 B 的片段之间,从而导致 B 片段被丢弃。

因此,虽然 IP 分片可以通过最小化用户标头来减少开销,但它可能会带来比其价值更多的麻烦。

于 2015-05-28T16:45:53.357 回答
4

据我所知,唯一会丢弃数据包而不是分段的情况(除非无论如何都会丢弃它)是标记为“不分段”的数据包。这些数据包将被丢弃而不是被分段。

分段数据包在其标头中具有标识符、分段偏移量和更多分段字段,当它们组合时,允许目标主机在收到所有分段后可靠地重新组合数据包。第一个片段的偏移量为零,最后一个片段的更多片段标志设置为零。如果两个数据包的标头发生突变,因此它们的片段偏移量被交换,但它们的校验和仍然有效,仍然有可能(尽管不太可能)重组一个不正确的数据包。这种情况发生的概率基本上为零。请记住,IP 不提供任何机制来确保数据有效负载的完整性,只提供标头中控制信息的完整性。

数据包分片必然会浪费带宽,因为每个分片都有一份原始数据报头的[大部分]副本。数据包可以被分割成每个片段只有 8 个字节,因此我们可以将一个 60 + 65536 字节的最大数据包分割成 60 * 8192 + 65536 个字节,在最坏的情况下产生大约 750% 的负载增加。我能想出的唯一一个你能领先的例子是,如果你对一个数据包进行分段,以便使用某种频分复用方案并行发送它的片段,并且知道其他通道是空闲的。在那一点上,它似乎仍然需要比节省更多的工作来检测这种情况并分割数据包而不是仅仅发送它。

如果您想了解更多信息,可以在IETF RFC 791中找到有关 IP 中数据包分段机制的所有基本细节。

于 2015-02-12T19:00:32.680 回答