Sockets ip碎片有多糟糕

Sockets ip碎片有多糟糕,sockets,networking,routing,ip,ip-fragmentation,Sockets,Networking,Routing,Ip,Ip Fragmentation,我知道在发送ip消息时,be和我的数据包目的地之间的网络路径中的每个跃点都会检查下一个跃点的MTU是否大于我发送的数据包的大小。如果是这样,数据包将被分割,两个数据包将分别发送到下一跳,只在目的地重新组装(或者,在某些情况下,在遇到的第一个NAT路由器)。 据我所知,这件事可能很糟糕,但我真的不明白为什么 我知道,如果连接倾向于丢弃大量数据包,丢失一个片段意味着我必须重新发送整个数据包(这实际上是我自己发现的唯一问题) 我的数据包是否有可能被丢弃而不是碎片化 如何识别数据包碎片?我能百分之百确

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

  • 我知道,如果连接倾向于丢弃大量数据包,丢失一个片段意味着我必须重新发送整个数据包(这实际上是我自己发现的唯一问题)
  • 我的数据包是否有可能被丢弃而不是碎片化
  • 如何识别数据包碎片?我能百分之百确定它们会正确地重新组装吗?例如,如果我几乎同时向同一个目的地发送两个长度相同的ip数据包,那么这两个数据包的片段被交换的可能性有多大,比如AAA,BBB重新组装成ABA,BAB
原则上,如果没有丢弃数据包并且正确地重新组装了数据包片段,那么实际上使用数据包片段似乎是一个好主意,可以节省本地带宽,避免发送越来越多的报头,而不仅仅是一个大数据包


谢谢

据我所知,数据包将被丢弃而不是碎片化的唯一情况(除非它将被丢弃),是标记为“不要碎片化”的数据包。这些数据包将被丢弃,而不是碎片化

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

数据包碎片必然会浪费带宽,因为每个碎片都有原始数据报报头的一个副本。数据包可以分段到每个片段只有8个字节,因此我们可以将最大大小为60+65536字节的数据包分段为60*8192+65536字节,在最坏的情况下产生约750%的有效负载增长。我能想到的唯一一个例子是,如果你在知道其他通道是免费的情况下,使用某种频分多路复用方案对一个数据包进行分段,以便并行发送其片段,那么你就可以走在前面。在这一点上,似乎需要比保存更多的工作来检测这种情况并划分数据包,而不仅仅是发送数据包


如果您想了解更多信息,可以在中找到有关IP数据包碎片机制的所有基本详细信息。

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

1)应用层损失增加

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

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

有些系统不重新组装碎片数据包

3)碎片可能导致重新排序

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

4)碎片可能导致难以调试的混乱行为

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


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

该链接并没有说Google Compute Engine没有重新组装碎片化的数据包,只是说它的MTU是1460,而不是通常假设的更高的数字(1500或1492)。这些信息还有其他参考资料吗?你是对的,我的链接没有显示这一点。我在2015年初使用GCE时发现了这一点。看起来它已经被报告并部分修复了。我更新了我的链接。下面是关于碎片的更多讨论: