C#UDP send / sendAsync太慢了

时间:2015-01-12 18:05:15

标签: c# performance udp

我正在尝试将许多小(~350字节)的UDP消息发送到不同的远程主机,每个远程主机一个数据包。我正在使用后台线程来听取回复

   private void ReceivePackets()
   {
       while (true)
       {
           try
           {
               receiveFrom = new IPEndPoint(IPAddress.Any, localPort);
               byte[] data = udpClientReceive.Receive(ref receiveFrom);
               // Decode message & short calculation
           }
           catch (Exception ex)
           {
               Log("Error receiving data: " + ex.ToString());
           }
       }
   }

和使用

发送消息的主线程
udpClientSend.SendAsync(send_buffer, send_buffer.Length, destinationIPEP);

UdpClient udpClientReceiveUdpClient udpClientSend都绑定到同一个端口 问题是SendAsync()需要大约15毫秒才能完成,我需要每秒发送几千个数据包。我已经尝试过使用udpClientSend.Send(send_buffer, send_buffer.Length, destination);,这同样慢。我还设置了更高的接收/发送缓冲区,我尝试设置udpClientSend.Client.SendTimeout = 1;无效。我怀疑它可能与远程主机改变每个数据包有关吗?如果是这种情况,在单独的线程中使用多个UDP客户端会使事情变得更快吗? 谢谢你的帮助!

注意: 网络带宽不是问题,我需要使用UDP而不是TCP。 我在这个网站上看到过类似的问题,但没有一个令人满意的答案。

修改

只有一个发送线程,它运行一个简单的循环,其中调用udpClientSend.SendAsync() 我正在查询DHT(bittorrent散列表)中的节点,因此多播不是一个选项(?) - 每个主机只获得1个数据包。
UDPClient类交换Socket类并使用AsyncSendTo()不会加快速度(或微不足道)。

我已经缩小了问题:将远程主机地址更改为某些固定IP&端口将吞吐量提高到超过3000个数据包/秒。因此,经常更改目标地址似乎是瓶颈。

我认为我的问题可能与UDP "Connect"-Speed in C#有关,UDPClient.Connect()正在减慢代码速度。如果是这样,有没有解决这个问题?它是语言还是操作系统问题?

1 个答案:

答案 0 :(得分:0)

为什么在发送之前使用UdpClient Connect?如果要设置默认主机,这是可选步骤。看起来您想要发送到多个目的地,这样您就可以在每次调用Send方法时设置远程主机。

如果你决定删除Connect方法,你可能会看到一个改进,但看起来你的代码中的其他地方仍然存在瓶颈。隔离发送呼叫和测量时间,然后开始添加更多步骤,直到找到减慢速度的步骤。

        var port = 4242;
        var ipEndPoint1 = new IPEndPoint(IPAddress.Parse("192.168.56.101"), port);
        var ipEndPoint2 = new IPEndPoint(IPAddress.Parse("192.168.56.102"), port);
        var buff = new byte[350];
        var client = new UdpClient();

        int count = 0;
        var stopWatch = new Stopwatch();
        stopWatch.Start();
        while (count < 3000)
        {
            IPEndPoint endpoint = ipEndPoint1;
            if ((count % 2) == 0)
                endpoint = ipEndPoint2;

            client.Send(buff, buff.Length, endpoint);
            count++;
        }
        stopWatch.Stop();

        Console.WriteLine("RunTime " + stopWatch.Elapsed.TotalMilliseconds.ToString());