我对UDP的理解是,虽然MTU大小有限制,但如果数据报超过MTU,它将在IP层被分段,传输作为单独的数据包,然后在接收端进行重构。如果其中一个分段被丢弃,UDP层将丢弃整个数据报。如果一切都到达,IP层重新构造数据报,UDP应该将其作为一个整体接收。然而,这并不是我所经历的行为。下面是一个简单服务器循环.NET中的UDP .Receive()返回一个分段为1k部分的数据报
var udp = new UdpClient(port);
while (true) {
IPEndPoint remote = new IPEndPoint(IPAddress.Any, 0);
byte[] payload = udp.Receive(ref remote);
Console.WriteLine($"Received {payload.Length}, IP: {remote}");
}
和经由netcat
发送数据的2999 bytes
如下
head -c 2999 /dev/urandom | nc -4u -w1 localhost 8999
服务器环路与大小1024
,1024
和951
字节的有效载荷接收三次。由于2*1024 + 951 = 2999
,似乎很明显,我打算发送的数据实际上是发送的,但UdpClient
正在接收它作为三个不同的数据报。
这似乎与UDP层在整个数据报上工作的事实不一致。应该在直接使用UDP时实现自己的片段重构逻辑吗?或者有没有办法只接收完整的数据报?
我不是专家,但默认[DontFragment](https://msdn.microsoft.com/en-us/library/system.net.sockets.udpclient.dontfragment(v = vs.110).aspx )是'true',尝试在接收时将其设置为false。但是,如果以套接字为例,我希望你负责组合数据,因为'接收'方法将(看起来)阻塞,直到接收到数据或缓冲区已满为止,请参阅[本问题](https:// stackoverflow.com/q/2319521/1997232)提供了一些提示。 – Sinatr
分片是由第3层上的IP数据包上的路由器进行的。 TCP和UDP不会分段。例如,TCP段,这与IP碎片完全不同。 –