2017-10-04 55 views
0

我对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 

服务器环路与大小10241024951字节的有效载荷接收三次。由于2*1024 + 951 = 2999,似乎很明显,我打算发送的数据实际上是发送的,但UdpClient正在接收它作为三个不同的数据报。

这似乎与UDP层在整个数据报上工作的事实不一致。应该在直接使用UDP时实现自己的片段重构逻辑吗?或者有没有办法只接收完整的数据报?

+0

我不是专家,但默认[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

+0

分片是由第3层上的IP数据包上的路由器进行的。 TCP和UDP不会分段。例如,TCP段,这与IP碎片完全不同。 –

回答

0

你对UDP的理解确实是对的。只要所有片段到达目的地,协议就会透明地为你处理分片和重组。我最初以为head可能会将您的数据以1024字节的块传递给netcat,但情况并非如此。

实际上是相反的情况:在您的系统netcat正在从stdin以1024字节的块读取并且每次生成一个新的UDP数据包。看起来netcat最适合用于处理连续的数据流,这些数据流对低层分组方式基本无关紧要。

更多信息请见this StackOverflow question