【问题标题】:UDP .Receive() in .NET returns a datagram fragmented in 1k parts.NET 中的 UDP .Receive() 返回一个分成 1k 部分的数据报
【发布时间】: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 次大小为 10241024951 字节的有效负载。由于2*1024 + 951 = 2999,很明显我打算发送的数据实际上已发送,但UdpClient 将其作为三个不同的数据报接收。

这似乎与 UDP 层作为一个整体处理数据报的事实不一致。直接使用 UDP 时是否应该实现自己的片段重建逻辑?或者有没有办法只接收完整的数据报?

【问题讨论】:

  • 我不是专家,但DontFragment默认为true,接收时尽量设置为false。但是,如果以套接字为例,我希望您负责合并数据,因为 Receive 方法将(看起来)简单地阻塞,直到接收到数据或缓冲区已满,请参阅 this question 以获得一些提示。跨度>
  • 分段是由路由器在第 3 层对 IP 数据包进行的。 TCP 和 UDP 不会分片。例如,TCP 分段,这与 IP 分段完全不同。

标签: c# .net networking udp


【解决方案1】:

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

实际上是相反的情况:在您的系统上,netcat 以 1024 字节的块从 stdin 读取并每次生成一个新的 UDP 数据包。似乎netcat 最适合用于处理连续的数据流,这些数据流大多与较低层的打包方式无关。

更多信息请访问this StackOverflow question

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-29
    • 1970-01-01
    • 1970-01-01
    • 2016-01-29
    • 2015-05-05
    • 2012-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多