【问题标题】:How can I set the buffer size for the underneath Socket UDP? C#如何设置底层 Socket UDP 的缓冲区大小? C#
【发布时间】:2012-03-13 16:39:55
【问题描述】:

众所周知,对于 UDP 接收,我们使用 Socket.ReceiveFrom 或 UdpClient.receive

Socket.ReceiveFrom 接受您的字节数组以放入 udp 数据。

UdpClient.receive 直接返回数据所在的字节数组

我的问题是如何设置 Socket 内部的缓冲区大小。我认为操作系统维护自己的缓冲区来接收 UDP 数据,对吧?例如,如果一个 udp 数据包发送到我的机器,操作系统会将其放入缓冲区并等待我们到 Socket.ReceiveFrom 或 UdpClient.receive,对吗?

如何更改该内部缓冲区的大小?

我试过Socket.ReceiveBuffSize,对UDP完全没有效果,而且明明说是对TCP窗口的。我也做了很多实验,证明 Socket.ReceiveBufferSize 不适用于 UDP。

谁能分享一些关于 UDP 内部缓冲区的见解???

谢谢

我在这里看到了一些帖子,例如,

http://social.msdn.microsoft.com/Forums/en-US/ncl/thread/c80ad765-b10f-4bca-917e-2959c9eb102a

Dave 说 Socket.ReceiveBufferSize 可以为 UDP 设置内部缓冲区。我不同意。

我做的实验是这样的:

27 台主机同时(至少几乎)在一个 LAN 内向我发送一个 10KB 的 udp 数据包。我有一个while循环来处理每个数据包。对于每个数据包,我创建一个线程来处理它。我使用 UdpClient 或 Socket 接收数据包。

我丢失了大约 50% 的数据包。我认为这是UDP发送的爆发,我无法及时处理所有这些。

这就是我想增加 UDP 缓冲区大小的原因。比如说,如果我把缓冲区大小改成 1MB,那么缓冲区可以接受 27 * 10KB = 270KB 的数据,对吧?

我尝试将 Socket.ReceiveBufferSize 更改为许多值,但它根本没有效果。

有人可以帮忙吗?

【问题讨论】:

    标签: c# sockets udp buffer


    【解决方案1】:

    我经常使用 .NET UDPClient 并且一直使用Socket.ReceiveBufferSize 并且效果很好。在内部,它使用ReceiveBuffer 参数调用Socket.SetSocketOption。下面是一些可以用来测试的快速、简单的代码:

    public static void Main(string[] args)
    {
      IPEndPoint remoteEp = null;
      UdpClient client = new UdpClient(4242);
      client.Client.ReceiveBufferSize = 4096;
    
      Console.Write("Start sending data...");
      client.Receive(ref remoteEp);
      Console.WriteLine("Good");
    
      Thread.Sleep(5000);
      Console.WriteLine("Stop sending data!");
      Thread.Sleep(1500);
    
      int count = 0;
      while (true)
      {
        client.Receive(ref remoteEp);
        Console.WriteLine(string.Format("Count: {0}", ++count));
      }
    }
    

    尝试调整传递给 ReceiveBufferSize 的值。我测试了在 5 秒内持续发送数据流,得到 10 个数据包。然后我增加了x4,下一次得到了38个数据包。

    我会查看您网络中可能丢弃数据包的其他地方。特别是因为您在other post 中提到您正在发送 10KB 数据包。当发送到 MTU 大小的数据包时,这 10KB 将被分段。如果该系列中的任何 1 个数据包被丢弃,则整个数据包都将被丢弃。

    【讨论】:

    • @heavyd:感谢您的回复。我的代码和你的非常相似。但如果你有兴趣,你可以做一个简单的实验。我们有两个单独的类——服务器和客户端。在您的 Client.cs 中,您只需使用 UdpClient 将 200 个数据包(每个 10KB)发送到您的本地端口 8888。(无论您想要什么端口)在您的 Server.cs 中,您确实会不断收到,就像您的代码中显示的一样,请首先运行你的 server.cs。我的结果是可以接收 90% 的数据包。关键是UDP发送是太多数据包到达并且您的服务器无法处理的突发。并且缓冲区溢出。
    • 是的,您是说将 ReceiveBufferSize 从一个值(例如 4096)调整为更高的值(例如 4 * 4096)没有任何作用?
    • @heavyd,我能知道 ReceiveBufferSize 的上限是多少吗?
    • @heavyd:在上面的本地实验中,有效果在不设置ReceiveBufferSize的情况下,接收到90%的数据包。如果我把它增加到16*4096,就可以全部接收了。但在我最初的实验中,它不起作用。
    • @Jack,我不确定上限。我最初的猜测是 64K,但我找不到任何支持文档。在你的实验之后,你确定你的网络在数据包到达你的计算机之前没有丢弃它们。您可能使混合中某处的交换机饱和,并在那里丢失数据包,而不是计算机上的堆栈。
    【解决方案2】:

    设置 ReceiveBufferSize 的问题是您需要在创建 UdpClient 对象后直接设置它。在获取 ReceiveBufferSize 的值时,我的更改没有得到反映,我遇到了同样的问题。

    UdpClient client = new UdpClient()
    //no code inbetween these two lines accessing client.
    client.Client.ReceiveBufferSize = somevalue
    

    【讨论】:

      猜你喜欢
      • 2011-01-25
      • 1970-01-01
      • 2015-05-18
      • 2014-04-28
      • 1970-01-01
      • 2021-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多