代码之家  ›  专栏  ›  技术社区  ›  AK_

如何编写.Net UDP可伸缩服务器

  •  2
  • AK_  · 技术社区  · 14 年前

    我需要写一个非常高负载的UDP服务器。我在用.Net。如何使用Socket类来实现这一点?

    我熟悉winsock API和完成端口,在那里我要做的是使用几个线程来接受使用完成端口的套接字,并以相同的方式接收套接字。

    我的服务器需要非常快速地处理很多小的UDP包,我想异步地接收它们,我如何使用.net来实现这一点?

    如果有人有一个很好的.net例子,这当然会有很大帮助。

    2 回复  |  直到 14 年前
        1
  •  1
  •   Steve Ellinger    14 年前

    我发现最小化丢弃的数据包的方法是,像您提到的那样,从套接字异步读取数据,但是要将读取的字节放入线程安全队列中,然后让另一个线程从队列中读取并处理字节。如果您使用的是.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方法都可以使用同一个事件来完全关闭。

        2
  •  1
  •   cmeerw    14 年前

    如果只有一个套接字,并且可以独立处理UDP数据包,那么最好的方法实际上是使用一个线程池,其中每个线程调用一个阻塞接收。操作系统将负责唤醒一个等待的线程来接收/处理数据包。这样可以避免异步I/O例程带来的任何开销。