首页 > 解决方案 > UDP 接收器是否能够一次处理数千个接收到的数据包?C#

问题描述

当许多 UDP 消息同时出现时,我担心会收到不完整的 UDP 包。

  1. 微软是否在操作系统中包含某种控制器来捕获 UDP,然后如果有程序正在监听,则将它们连续传递到指定的端口(消息到达的端口)?

  2. 我创建了这种代码。这是否有助于捕获 5000 条消息?ProcessReceivedBytes方法应该异步运行,并且在处理字节时它应该已经再次监听,我正确吗?

    while (_run)
                {
                    byte[] bytes = _client.Receive(ref _endPoint);
                    ProcessReceivedBytes(bytes);
                }
    

下面这个类的完整代码。实现是在程序中创建实例然后开始监听。

    public delegate void LoggingMethod(string log);
    public delegate void LoggingMethodError(Exception e);
    public delegate void ProcessReceivedBytes(byte[] receivedBytes);
    public class UDPListener
    {
        private bool _isListening;
        private bool _isClosed;
        private bool _run;
        private int _port;
        private IPAddress _ipAdress;
        private IPEndPoint _endPoint;
        private UdpClient _client;
        private LoggingMethod _logNormal;
        private LoggingMethodError _logError;
        private ProcessReceivedBytes _processReceived;
        Task _processBytes;

    public int Port { get => _port;}
    public string IpAdress { get => _ipAdress.ToString(); }

    public UDPListener(int port, string ipAdress, ProcessReceivedBytes processReceived)
    {
        _port = port;
        _ipAdress = IPAddress.Parse(ipAdress);
        _processReceived = processReceived;
    }

        public UDPListener(int port, string ipAdress, ProcessReceivedBytes processReceived, LoggingMethod logNormalState, LoggingMethodError logErrorState) : this(port, ipAdress, processReceived)
        {
            _logNormal = logNormalState;
            _logError = logErrorState;
        }


        public async Task StartListening()
        {
            LogNormalState("Setting up client and endpoint.");

            _run = true;
            _client = new UdpClient(_port);
            _isClosed = false;
            _endPoint = new IPEndPoint(_ipAdress, _port);

            LogNormalState("Starting to listen.");

            try
            {
                _isListening = true;
                while (_run)
                {
                    byte[] bytes = _client.Receive(ref _endPoint);
                    ProcessReceivedBytes(bytes);
                }
            }
            catch (SocketException e)
            {
                if (e.ErrorCode == 10004)
                {
                    LogNormalState("A socket exception (10004) was thrown. It's okay if the listener was closed by method StopListening.");
                }
                else
                {
                    await LogErrorState(e);
                }
            }
            catch (Exception e)
            {
                await LogErrorState(e);
            }
            finally
            {
                CloseClient();
            }
        }

        public bool IsListening()
        {
            return _isListening;
        }

        public bool IsClosed()
        {
            return _isClosed;
        }

        public void StopListening()
        {
            int waiterLimit = 100;
            int waiterCounter = 0;

            LogNormalState("Listening stopped by method StopListening.");
            _run = false;
            LogNormalState("Waiting 100ms before socket hard closure.");
            while (waiterCounter <= waiterLimit)
            {
                Thread.Sleep(1);
                waiterCounter++;
            }
            CloseClient();
        }

        private void CloseClient()
        {
            if (!IsClosed())
            {
                _isListening = false;
                LogNormalState("Listening stopped.");
                LogNormalState("Closing client.");
                _client.Close();
                _isClosed = true;
            }
        }

        private void LogNormalState(string log)
        {
            if (_logNormal != null)
            {
                _logNormal.Invoke(log);
            }
        }

        private async Task LogErrorState(Exception e)
        {
            if (_logError != null)
            {
                _logError.Invoke(e);
            }
        }

        private async Task ProcessReceivedBytes(byte[] bytes)
        {
            if (_processReceived != null)
            {
                _processReceived.Invoke(bytes);
            }
        }

    }
}

标签: c#udp

解决方案


推荐阅读