【发布时间】:2017-10-04 08:15:11
【问题描述】:
我对 UDP 的理解是,虽然 MTU 大小有限制,但如果数据报超过 MTU,它会在 IP 层被分片,作为单独的数据包传输,然后在接收端重建。如果其中一个片段被丢弃,UDP 层将丢弃整个数据报。如果一切都到了,IP 层会重新构造数据报,UDP 应该将其作为一个整体接收。
但这不是我正在经历的行为。这是一个简单的服务器循环
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
服务器循环接收 3 次大小为 1024、1024 和 951 字节的有效负载。由于2*1024 + 951 = 2999,很明显我打算发送的数据实际上已发送,但UdpClient 将其作为三个不同的数据报接收。
这似乎与 UDP 层作为一个整体处理数据报的事实不一致。直接使用 UDP 时是否应该实现自己的片段重建逻辑?或者有没有办法只接收完整的数据报?
【问题讨论】:
-
我不是专家,但DontFragment默认为
true,接收时尽量设置为false。但是,如果以套接字为例,我希望您负责合并数据,因为Receive方法将(看起来)简单地阻塞,直到接收到数据或缓冲区已满,请参阅 this question 以获得一些提示。跨度> -
分段是由路由器在第 3 层对 IP 数据包进行的。 TCP 和 UDP 不会分片。例如,TCP 分段,这与 IP 分段完全不同。
标签: c# .net networking udp