原始套接字的数据包碎片
Posted
技术标签:
【中文标题】原始套接字的数据包碎片【英文标题】:packet fragmentation for raw sockets 【发布时间】:2011-05-10 10:14:03 【问题描述】:如果我使用原始套接字发送大小为 3000 字节的 UDP 数据包,我是否需要在代码中自己处理数据包碎片,还是应该使用原始套接字处理类似于 DGRAM 套接字的碎片?
【问题讨论】:
如果我没记错的话,我怀疑我是这个,你必须担心丢包等等,UDP是一种尽力而为的协议。 数据包(如果已接收)很好 - 但是,不能保证保留订单。显然,如果您是发送/响应/发送/响应,这不是问题,但如果您正在流式传输,则会出现问题。 UDP 的问题在于,一旦你实现了所有的内务处理,你就希望你一开始就完成了 TCP。通常,当您不担心丢失数据包时,情况并非如此。 你能澄清一下在这种情况下你所说的 raw 到底是什么意思吗?您是否在编写原始以太网帧、原始 IP 数据包?你在什么系统上做这个?有些系统提供某种“半-n-半”套接字... 我的意思是通过 IP_RAW 套接字发送 IP 数据包。 后续问题在这里***.com/questions/4191253/…。 【参考方案1】:对于 Linux,答案是肯定的。如果你看一下 Linux 的 raw socket implementation,原始套接字不会发生重组。
【讨论】:
【参考方案2】:好吧,如果您使用的是 UDP,那么您实际上并没有发送 RAW。 RAW 根本就没有 IP,在这种情况下,是的,您必须自己处理碎片。
使用 UDP,您可以获得 IP 分片支持,恕我直言,这对于应该尽量减少冲突的短途网络来说已经足够好了。使两个系统之间的链接成为一个专用子网,这根本不是问题。
TCP 通过 UDP 为您带来的好处(除其他外)是堆栈的能力,如果它以某种方式丢失或损坏,则只需重新发送一个片段。如果发生这种情况,使用 UDP 必须丢弃整个消息。不过,这样做会产生开销,对于大多数现代网络,您可能可以接受这种权衡。
【讨论】:
同意其他答案缺少“原始”的观点。虽然不同意您的结论,但某些系统具有“原始 IP”套接字,您仍然指定 ip 标头的源地址和目标地址,但您自己编写数据包的其余部分。在这种情况下,将有一个 IP 标头(一半由应用程序构建,一半由较低级别管理),并且它会像往常一样有一个 DF 位。 @awoodland - 很有趣。我的经验主要是编写自己的堆栈。如果用户正在处理填写 IP 数据包,我认为他们还必须处理将传入的 IP 片段组装成消息。 我以为问题只是关于传输,因为它询问了发送!问题是在这种情况下,“原始”的含义并不是很清楚。 我在***.com/questions/4191253/… 添加了关于如何处理碎片的后续问题。谢谢你的回答。【参考方案3】:根据您的系统,这可以完全不同地处理。例如,在 Linux 上,如果您尝试发送大于(已知)路径 MTU 的内容,您可以要求较低层处理路径 MTU 发现并给出错误 (EMSGSIZE)。
您所说的原始套接字有多“原始”?其他系统可能只是让您控制 DF 位(或者您可能自己构建大部分 IP 标头),在这种情况下,行为也将取决于此。
通常,如果您使用 DF 集进行传输,您通常会选择在用户空间中查看错误,或者让主机上的较低级别处理 PMTU 发现并阻止您发送过大的内容。如果您不设置 DF,那么您(可能)会看到沿路径来自路由器的适当碎片。
【讨论】:
【参考方案4】:底层协议 IP 仍然处理碎片。只要你不设置DF(不要分段)位,我认为你应该没问题。
【讨论】:
【参考方案5】:不,数据包分段在较低级别处理。您应该确切地看到您放入数据包的内容回来了。也就是说UDP保证了消息边界。
【讨论】:
以上是关于原始套接字的数据包碎片的主要内容,如果未能解决你的问题,请参考以下文章