UDP

 internal class IocpUdpServer {
        private Socket _listen;
        private bool _isRun;
        private readonly int _bufferLength;

        //Sae池
        private readonly SaeQueuePool _saeQueue = new SaeQueuePool(256);

        /// <summary>
        /// 获取SEA池中的可用项数量
        /// </summary>
        public int SeaCount => _saeQueue.Count;

        /// <summary>
        /// 获取当前运行的IP
        /// </summary>
        public string Ip { get; }

        /// <summary>
        /// 获取系统分配的UDP端口号
        /// </summary>
        public int Port { get; }

        /// <summary>
        /// 
        /// </summary>
        public long ReceivedBytesCount { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        public long SendBytesCount { get; private set; }

        /// <summary>
        /// 收到的报文数量
        /// </summary>
        public int ReceivedCount { get; private set; }

        /// <summary>
        /// 发送的报文数量
        /// </summary>
        public int SendCount { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        public bool IsRunning => _isRun;

        //报文接收处理队列
        private readonly IUdpRequestHandler _handlerQueue;

        /// <summary>
        /// 实例化UDP服务器,并直接启动监听
        /// </summary>
        /// <param name="handlerQueue">报文接收处理队列</param>
        /// <param name="bufferLength">缓冲区大小</param>
        /// <param name="port">监听的端口号</param>
        public IocpUdpServer(IUdpRequestHandler handlerQueue, string ip, int port, int bufferLength = 1024) {
            _handlerQueue = handlerQueue;
            _bufferLength = bufferLength;

            Ip = ip;
            Port = port;
        }

        /// <summary>
        /// 收到数据事件
        /// </summary>
        public event EventHandler<ReceiveDataEventArgs> ReceiveData;

        /// <summary>
        /// 启动UPD监听,接收来自网络上的UDP消息
        /// </summary>
        public void Start() {
            //var local = new IPEndPoint(IPAddress.Any, Port);
            var local = new IPEndPoint(IPAddress.Any, Port);
            _listen = new Socket(local.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
            _listen.Bind(local);

            var socketAsync = new SocketAsyncEventArgs();
            socketAsync.SetBuffer(new byte[_bufferLength], 0, _bufferLength);
            socketAsync.Completed += SocketAsync_Completed;
            socketAsync.RemoteEndPoint = local;
            _isRun = true;

            StartReceive(socketAsync);
        }

        public void Stop() {
            Close();
        }

        /// <summary>
        /// 开始异步接收UDP消息
        /// </summary>
        private void StartReceive(SocketAsyncEventArgs socketAsync) {
            if (!_isRun) return;
            if (!_listen.ReceiveFromAsync(socketAsync))
                SocketAsync_Completed(_listen, socketAsync);
        }

        private void SocketAsync_Completed(object sender, SocketAsyncEventArgs e) {
            if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) {
                if (e.LastOperation == SocketAsyncOperation.ReceiveFrom) {
                    var data = new byte[e.BytesTransferred];
                    Buffer.BlockCopy(e.Buffer, e.Offset, data, 0, data.Length);

                    if (Settings.DebugUdpPacket)
                        LogConsole.Debug($"UDP Rcv:{data.ToHexString()},长度={data.Length}");

                    ReceivedBytesCount += e.BytesTransferred;
                    ReceivedCount++;

                    StartReceive(e);

                    //Console.WriteLine($"{DateTime.Now}	{e.RemoteEndPoint}	{buffer.Length}");
                    OnReceive((IPEndPoint)e.RemoteEndPoint, data);
                    return;
                }
            }

            StartReceive(e);
        }

        /// <summary>
        /// 远程端点收到消息处理
        /// </summary>
        private void OnReceive(IPEndPoint iPEndPoint, byte[] data) {
            if (!_isRun) return;
            if (iPEndPoint == null) return;

            //小于8字节的报文不处理
            if (data.Length < 8 + 4) {
                LogConsole.Debug("报文过短,抛弃:" + data.ToHexString());
                return;
            }

            //UDP的到达顺序不确定性可能导致问题
            //TODO:拆包
            var prefix = data[0];
            var subfix = data.Last();
            if (prefix != G.FrameHeader || subfix != G.FrameTail) {
                LogConsole.Debug("收尾错误,抛弃:" + data.ToHexString());
                return;
            }

            //Debug.WriteLine($"收到端点:{args.IpEndPoint},报文=> {data.ToHexString()}");

            _handlerQueue.Enqueue(new UdpRequestWrapper(data, iPEndPoint));

            //抛出收到数据事件
            ReceiveData?.Invoke(this, new ReceiveDataEventArgs {
                Data = data,
                IpEndPoint = iPEndPoint
            });
        }

        /// <summary>
        /// 向远程网络端点发送数据
        /// </summary>
        public void SendAsync(EndPoint endPoint, byte[] bytes) {
            if (!_isRun || _listen == null)
                return;

            //优先从可复用队列中取
            var socketSendAsync = _saeQueue.Dequeue();
            socketSendAsync.SetBuffer(bytes, 0, bytes.Length);
            socketSendAsync.RemoteEndPoint = endPoint;

            SendCount++;
            SendBytesCount += bytes.Length;

            if (Settings.DebugUdpPacket)
                LogConsole.Debug($"UDP Send:{endPoint},Data={bytes.ToHexString()}");

            //如果发送失败,则强制归队
            if (!_listen.SendToAsync(socketSendAsync))
                _saeQueue.Enqueue(socketSendAsync);
        }

        /// <summary>
        /// 关闭服务
        /// </summary>
        public void Close() {
            _isRun = false;
            _listen?.Close();
            _listen = null;
        }
    }

  

原文地址:https://www.cnblogs.com/robertyao/p/12713496.html