如何使用 C# UdpClient 发送大数据?

Posted

技术标签:

【中文标题】如何使用 C# UdpClient 发送大数据?【英文标题】:How to send large data using C# UdpClient? 【发布时间】:2011-01-20 03:26:05 【问题描述】:

我正在尝试使用 C# UdpClient 发送大量数据(超过 50 MB)。

所以一开始我把数据分成65507字节的块,循环发送。

for(int i = 0; i < packetCount; i++)
   myUdpClient.Send(blocks[i], block[i].Length, remoteEndPoint);

我的问题是只能接收到第一个数据包。 在发送第一个数据包期间,网络负载迅速增加到 100%,然后无法接收其他数据包。

我想获得尽可能多的数据吞吐量。

对不起我的英语! 提前感谢您的帮助。

【问题讨论】:

不拆分数据会怎样? 使用 Microsoft Network Monitor 3.3 查看数据包并确认到达。 如果我不拆分数据,udpClient.Send 调用会因为 udp-packet-size 最大而失败。 【参考方案1】:

对于那些说使用 TCP.... 的人来说,这是愚蠢的错误。虽然 TCP 是可靠的并且由内核维护的窗口是相当“设置并忘记”的协议,但是当涉及到想要使用 100% 吞吐量的人时,TCP 不会这样做(它的节流太猛,并且等待由于 RTT,ACK 会自动将至少 50% 的数据丢弃)。

对于最初的问题,您在该 for 循环中不停地发送 UDP 数据包,窗口填满,然后立即丢弃任何新数据,甚至不尝试上线。您还将数据拆分得太大。我建议建立你自己的节流机制,从每秒 2k 段开始,然后慢慢增加。每个“段”包含一个 SEQ(确认或 ACK 的序列标识符)和 OFF(此数据集文件内的偏移量)。当数据被标记时,让服务器跟踪这些标记。当对方得到它们时,它将 SEQ 编号存储在 ACK 列表中,任何丢失的 SEQ 编号都放入 NACK 计时器列表中,当计时器用完时(如果尚未收到),它会移动到 NACK 列表.接收方应该每隔几秒左右在一次传输中从 ACK 列表中发送 5 个左右的 ACK 以及最多 5 个 NACK。如果发送者收到这些消息并且有任何 NACK,它应该立即关闭并重新发送丢失的片段,然后再继续。确认的数据可以从内存中释放。

祝你好运!

【讨论】:

如果您想要高速 LAN 通信,请禁用 Nagle。 TCP 通常仍然更快,因为大多数 NIC 都为分段提供硬件加速。【参考方案2】:

我不知道具体的 .Net 实现,它可能正在缓冲您的数据,但 UDP 数据报通常受链路 MTU 的限制,在普通以太网上为 1500(减去 20 个字节的 IP 标头和 8 个字节的 UDP标题。)

明确允许 UDP 丢弃和重新排序数据报,并且没有 TCP 中的流量控制。

超过发送方的套接字发送缓冲区将在发送尝试后忽略网络堆栈,直到缓冲区空间再次可用(为此,您需要检查send() 的返回值。)

编辑:

我强烈建议使用 TCP 进行大文件传输。 TCP 为您提供排序(您不必跟踪丢弃和重新排序的数据包。)它具有高级流量控制(因此快速发送方不会压倒慢速接收方。)它还进行路径 MTU 发现(即找出最优数据打包并避免 IP 碎片。)否则您将不得不自己重新实现这些功能。

【讨论】:

65507 的数据包大小在我的 LAN 中工作正常,send() 调用总是返回 65507 那么接收者从第一个“数据包”中得到了什么? 65507 字节? 您看到 IP 片段在网络上流动吗?这就是 CPU 峰值 - 将 64K 数据报分段为 MTU 大小的数据包。 对不起,我听不懂。请用更简单的英文发布最后一条消息!谢谢! TCP/IP 堆栈必须对您提供给它的 64KB 数据进行分段。这表明 CPU/网络负载增加。【参考方案3】:

我不想这么说,但你需要让线程休眠。你正在超载你的吞吐量。 UDP对于无损数据传输不是很好。 UDP 适用于您不介意丢弃一些数据包的情况。

【讨论】:

除了丢弃一些数据包外,UDP 甚至不保证它们会按原始顺序接收,这也可能是一个问题。 我通常有多达 10 个 udp 数据包,具体取决于彼此...所以如果一个数据包丢失,我也会丢弃其他 9 个数据包,如果数据包丢失也不是问题.这就是我不想使用 tcp 的原因……我还认为使用 UDP 可以获得更好的网络吞吐量。 加 1 .. 表示“UDP 适用于您不介意丢弃一些数据包的情况”【参考方案4】:

可靠 - 不,您不会使用 UDP 来实现。

据我了解,这对于一次发送到多台计算机(广播)是有意义的。

在这种情况下,

与他们每个人建立 TCP 连接, 将数据拆分成块, 给每个区块一个 ID, 通过 TCP 连接向每台计算机发送 ID 列表, 使用 UDP 广播数据, 通知客户端(通过 TCP)数据传输结束, 客户端应该要求重新发送丢弃的数据包

【讨论】:

以上是关于如何使用 C# UdpClient 发送大数据?的主要内容,如果未能解决你的问题,请参考以下文章

使用 UdpClient C# 发送对象

C# UdpClient使用

UDP 协议 C# UdpClient乱序接收数据包丢失的问题 Socket ReceiveBufferSize

C#里使用UdpClient和线程来创建UDP网络通讯

C#里使用UdpClient和线程来创建UDP网络通讯

C# UdpClient 设置超时时间