Search code examples
c#.netudpsharppcap

Is there any possible way to send Udp requests faster in SharpPcap (.NET 8)?


I'm unable to achieve a delay between requests of less than 50 microseconds (10 microseconds is required). No optimizations, such as running on multiple warmed-up threads, seem to help (apparently, there's some kind of lock under the hood). The requests are sent via an Ethernet cable. Are there any other settings or approaches that could help reduce the delay?

    _device.OnPacketArrival += ProcessPacketArrival;
    _device.Open(DeviceModes.MaxResponsiveness | DeviceModes.NoCaptureLocal, -1);
    _device.NonBlockingMode = true;
    _device.StartCapture();

    //delay between requests 50+ microseconds
    _device.SendPacket(_cachedBytes.AsSpan());
    _device.SendPacket(_cachedBytes.AsSpan());

Tried: various configurations, multithreading and etc. Expect: delay between requests not more than 10 microseconds.

Solved: In my case, the solution was to use the SendQueue class from SharpPcap. Setting the size in the constructor and adding messages via SendQueue.Add with the required number of packets, you can then call _sendQueue.Transmit. In my scenario, the timeout between requests is about 5 microseconds, and between Transmits, it's 24 milliseconds.


Solution

  • In my case, the solution was to use the SendQueue class from SharpPcap. Sample:

    _device.OnPacketArrival += ProcessPacketArrival;
    _device.Open(DeviceModes.MaxResponsiveness | DeviceModes.NoCaptureLocal, -1);
    _device.NonBlockingMode = true;
    _device.StartCapture();
    
    const int QueueSize = 4096;
    using SendQueue sendQueue = new SendQueue(QueueSize);
    
    
    //This is how to add with no delay
    sendQueue.Add(ethernetPacket1.Bytes);
    sendQueue.Add(ethernetPacket2.Bytes);
    
    //if you want to control the delays between requests, add offset
    //This is how to add with custom delay
    int usecOffset = 0;
    int secOffset = 0;
    
    usecOffset += DelayBetweenRequestsUsec;
    secOffset += DelayBetweenRequestsSec;
    sendQueue.Add(ethernetPacket3.Bytes, secOffset, usecOffset);
    
    usecOffset += DelayBetweenRequestsUsec;
    secOffset += DelayBetweenRequestsSec;
    sendQueue.Add(ethernetPacket4.Bytes, secOffset, usecOffset);
    
    sendQueue.Transmit(_device, true);
    

    Make sure the size of SendQueue is sufficient (remember additional bytes for timeval for every packet depends on your OS Marshal.SizeOf<timeval_windows/timeval_macosx/timeval_unix>()). The Add method of SendQueue will return false, if it is not enough.

    This code is just an example.