devwork
devwork

Reputation: 1

C# udp server not reading fast enough

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);
    }
}

I wrote a simple program that sends packets of 100 bytes and the same machine as server receives packets asynchronously and stores in queue. Packets received is fine until number of packets are 83 Once I start increasing the number of packets more than 84 the rate of packets received falls through. As I understand this is because the client is not fast enough in reading the incoming packets and as the buffer overflows the packets are being lost. Is there any way that I can make server fast enough to receive the fast incoming packets.

There was similar question C# UDP packetloss though all packets arrive (WireShark) I think I am doing what the answer was suggested but still the issue persists.

Upvotes: 0

Views: 1489

Answers (1)

Dmitry
Dmitry

Reputation: 344

Well, it uses the same ip at the same port for both server and client:)

I did a test with your code. I have added 2 static vars static int sendIter = 0; static int recvIter = 0;

and run the app. It exits with sendIter = 84 and recvIter = 0..2-3 iterations

I think it happens because you begin async operation(BeginReceive) in the function and then immediately start for loop to send msgs. Under the hood BeginReceive starts the thread, but it has no chances to switch context to itself even if it's ready to process incoming message because of this for loop - it takes all cpu time.

Then i have added Thread.Sleep(1)(it will allow the app to switch thread context) right after client.Send and i got sendIter and recvIter equal

So i think the client is fast enough if it has cpu time

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);
    }
}

Upvotes: 0

Related Questions