如果我使用原始套接字发送大小为 3000 字节的 UDP 数据包,我是否需要在代码中自己处理数据包碎片,或者原始套接字是否应该处理类似于 DGRAM 套接字的碎片?
5 回答
好吧,如果您使用的是 UDP,那么您并没有真正发送 RAW。RAW 根本就没有 IP,在这种情况下,是的,您必须自己处理碎片。
使用 UDP,您可以获得 IP 的分段支持,恕我直言,这对于冲突应该最小的短途网络来说已经足够好了。使两个系统之间的链接成为专用子网,这根本不是问题。
TCP 通过 UDP(除其他外)为您购买的是堆栈的能力,如果它以某种方式丢失或被冲洗掉,则只需重新发送一个片段。如果发生这种情况,使用 UDP 必须丢弃整个消息。但是,这会产生开销,对于大多数现代网络,您可能可以接受这种权衡。
不,数据包碎片是在较低级别处理的。您应该确切地看到您放入数据包的内容回来了。也就是说,UDP 保证了消息边界。
底层协议 IP 仍然处理碎片。我认为,只要您不设置DF(不要分段)位就应该没问题。
根据您的系统,这可以完全不同地处理。例如,在 Linux 上,如果您尝试发送大于(已知)路径 MTU 的内容,您可以要求较低层处理路径 MTU 发现并给出错误 (EMSGSIZE)。
您正在谈论的原始套接字有多“原始”?其他系统可能只让您控制 DF 位(或者您可能自己构建大部分 IP 标头),在这种情况下,行为也将取决于此。
通常,如果您使用 DF 集进行传输,您通常会选择在用户空间中查看错误,或者让主机上的较低级别处理 PMTU 发现并阻止您发送太大的内容。如果您不设置 DF,那么您(可能)会看到沿路径来自路由器的适当碎片。
对于 Linux,答案是肯定的。如果你看一下 Linux 的原始套接字实现,原始套接字不会发生重组。