Как написать .Net UDP Масштабируемый сервер - PullRequest
2 голосов
/ 24 октября 2010

Мне нужно написать UDP-сервер с очень высокой нагрузкой. Я использую .Net. Как мне использовать класс Socket для достижения этой цели?

Я знаком с Winsock API, портами завершения и тем, что я хотел бы там сделать, - использовать несколько потоков для приема сокетов с использованием порта завершения, а также для получения таким же образом.

Мой сервер должен очень быстро обрабатывать множество маленьких пакетов UDP, и я хочу получать их асинхронно, как мне это сделать с помощью .net?

Я думал о вызове BeginReceive несколько раз, но это вроде глупо ...

Если у кого-то есть хороший пример .net для этого, он, конечно, очень поможет.

Ответы [ 2 ]

1 голос
/ 25 октября 2010

Если у вас есть только один сокет и вы можете обрабатывать UDP-пакеты независимо друг от друга, тогда на самом деле наилучшим подходом будет использование пула потоков, где каждый поток вызывает блокирующее получение.ОС позаботится о пробуждении одного из ожидающих потоков для приема / обработки пакета.Таким образом, вы можете избежать любых накладных расходов, вносимых процедурами async-I / O.

1 голос
/ 24 октября 2010

Я обнаружил, что для минимизации отброшенных пакетов необходимо асинхронное чтение из сокета, как вы упомянули, но для помещения прочитанных байтов в безопасную очередь потока, а затем для чтения другого потока из очереди и обработки байтов. Если вы используете .Net 4.0, вы можете использовать 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;
            }
        }
    }
}

Примечание: _StopEvent - это ManualResetEvent, так что методы ReceiveCallback и ReadReceiveQueue могут использовать одно и то же событие для чистого отключения.

...