views:

24

answers:

2

Hello StackOverflow!

I need to write a very high load UDP server. I'm using .Net. How do I use the Socket class to achieve this?

I am familiar with the winsock API, and completion ports, and what i would do there, is to use several threads to accept sockets using a completion port, and also to receive in the same manner.

My server needs to process a LOT of small UDP packets very quickly, and i want to receive them asynchronously, how do i do this using .net?

I thought of calling BeginReceive several times, but that kinda seems silly...

If anyone has a good .net example for this it would of course help a lot.

A: 

What I have found to minimize dropped packets is to read from the socket asynchronously as you mentioned, but to put the bytes read into a thread safe queue, then have another thread read off the queue and process the bytes. If you are using .Net 4.0 you could use ConcurrentQueue:

public class SomeClass {
    ConcurrentQueue<IList<Byte>> _Queue;
    Byte[] _Buffer;
    ManualResetEvent _StopEvent;
    AutoResetEvent _QueueEvent;
    private void ReceiveCallback(IAsyncResult ar) {
        Socket socket = ar.AsyncState as Socket;
        Int32 bytesRead = socket.EndReceive(ar);
        List<Byte> bufferCopy = new List<byte>(_Buffer);
        _Queue.Enqueue(bufferCopy);
        _QueueEvent.Set();
        if(!_StopEvent.WaitOne(0)) socket.BeginReceive(...);
        return;
    }
    private void ReadReceiveQueue() {
        WaitHandle[] handles = new WaitHandle[] { _StopEvent, _QueueEvent };
        Boolean loop = true;
        while (loop) {
            Int32 index = WaitHandle.WaitAny(handles);
            switch (index) {
                case 0:
                    loop = false;
                    break;
                case 1:
                    // Dequeue logic here
                    break;
                default:
                    break;
            }
        }
    }
}

Note: the _StopEvent is a ManualResetEvent so that both the ReceiveCallback and ReadReceiveQueue methods can use the same event to shut down cleanly.

Steve Ellinger
A: 

If you only have a single socket and you can process UDP packets independently of each other, then the best approach would actually be to use a thread pool where each thread invokes a blocking Receive. The OS will take care of waking up one of the waiting threads to receive/process the packet. That way you can avoid any overhead introduced by the async-I/O routines.

cmeerw