【问题标题】:C# udp server not reading fast enoughC# udp 服务器读取速度不够快
【发布时间】:2017-02-20 09:58:25
【问题描述】:
public class RCon
{
    static readonly ConcurrentQueue<byte[]> ReceivedPacketQueue = new ConcurrentQueue<byte[]>();
    static IPEndPoint _ipEndPoint = new IPEndPoint(IPAddress.Parse("10.XXX.XX.117"), 2222); 

    static void Main(string[] args)
    {
        var client = new UdpClient
                         {
                             ExclusiveAddressUse = false,
                             Client = { ReceiveBufferSize = 8192 }
                          };

        client.Client.Bind(_ipEndPoint);
        client.BeginReceive(OnUdpData, client);

        var message = new byte[100];
        int numberOfPackets ;

        for (numberOfPackets = 0; numberOfPackets < 84; numberOfPackets++)
        {
             client.Send(message, message.Length, _ipEndPoint);
        }
    }

    static void OnUdpData(IAsyncResult result)
    {
        var socket = result.AsyncState as UdpClient;
        var message = socket.EndReceive(result, ref _ipEndPoint);
        ReceivedPacketQueue.Enqueue(message);
        socket.BeginReceive(OnUdpData, socket);
    }
}

我写了一个简单的程序,它发送 100 字节的数据包,并且与服务器相同的机器异步接收数据包并存储在队列中。收到的数据包很好,直到数据包数量为 83 一旦我开始增加超过 84 个数据包的数量,接收数据包的速率就会下降。据我了解,这是因为客户端读取传入数据包的速度不够快,并且由于缓冲区溢出,数据包正在丢失。有什么方法可以让服务器足够快地接收快速传入的数据包。

有类似的问题C# UDP packetloss though all packets arrive (WireShark) 我想我正在按照建议的答案做,但问题仍然存在。

【问题讨论】:

  • 看起来你向自己发送消息 - 从 ip 10.170.25.117:2222 到 ip 10.170.25.117:222,实际上我不知道在这种情况下它会如何工作尝试设置两个发送并将缓冲区接收到最大值,即 65536
  • 谢谢德米特里。是的,同一台机器充当服务器和客户端。即使我设置为最大缓冲区大小并增加数据包的速率(从 84 到 1200 或更大的数量),我也会开始丢失数据包,因为读取速度不够快并且会发生溢出缓冲区。我的问题是我可以以任何方式改进异步开始接收(OnUdpData)代码以加快数据包的读取速度。

标签: c# sockets udp


【解决方案1】:

好吧,它为服务器和客户端在同一端口使用相同的 ip:)

我对您的代码进行了测试。我添加了 2 个静态变量 静态 int sendIter = 0; 静态 int recvIter = 0;

并运行应用程序。它以 sendIter = 84 和 recvIter = 0..2-3 次迭代退出

我认为这是因为您在函数中开始异步操作(BeginReceive),然后立即开始 for 循环以发送消息。 在引擎盖下 BeginReceive 启动线程,但它没有机会将上下文切换到自身,即使它准备好处理传入的消息,因为这个 for 循环 - 它需要所有 cpu 时间。

然后我在 client.Send 之后添加了 Thread.Sleep(1)(它将允许应用程序切换线程上下文),我得到 sendIter 和 recvIter 相等

所以我认为客户端如果有 cpu 时间就足够快了

class Program
{
    static readonly ConcurrentQueue<byte[]> ReceivedPacketQueue = new ConcurrentQueue<byte[]>();
    static IPEndPoint _ipEndPoint = new IPEndPoint(IPAddress.Parse("192.168.4.142"), 2222);
    static int sendIter = 0;
    static int recvIter = 0;

    static void Main(string[] args)
    {
        var client = new UdpClient
        {
            ExclusiveAddressUse = false,
            Client = { ReceiveBufferSize = 8192 }
        };

        client.Client.Bind(_ipEndPoint);
        client.BeginReceive(OnUdpData, client);

        var message = new byte[100];
        int numberOfPackets;

        for (numberOfPackets = 0; numberOfPackets < 100; numberOfPackets++)
        {
            client.Send(message, message.Length, _ipEndPoint);
            Thread.Sleep(1);
            sendIter++;
        }

        Console.WriteLine(sendIter);
        Console.WriteLine(recvIter);
        Console.ReadKey();
    }

    static void OnUdpData(IAsyncResult result)
    {
        var socket = result.AsyncState as UdpClient;
        var message = socket.EndReceive(result, ref _ipEndPoint);
        ReceivedPacketQueue.Enqueue(message);
        recvIter++;
        socket.BeginReceive(OnUdpData, socket);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-05
    • 1970-01-01
    • 1970-01-01
    • 2013-09-05
    • 1970-01-01
    • 2013-12-16
    • 2012-10-17
    • 1970-01-01
    相关资源
    最近更新 更多