处理来自UdpClient.BeginReceive()的传入消息

时间:2013-02-18 23:08:32

标签: c# asynchronous .net-4.5 udpclient

好的,这是我的第一个堆栈溢出问题,所以请随时建议更好的方式询问或下次我应该包括什么。大部分时间我都可以谷歌来获得我的答案,但这个有点棘手...

我正在用C#编写一个监听UDP端口的Windows应用程序,然后处理传入的UDP消息。更具体地说,我正在使用UDPClient类并使用BeginReceive方法进行侦听。接收回调依次触发它自己的消息接收事件,然后再次重置UDP客户端。此“MessageReceived”事件随后由处理器对象处理。

我认为这一切都非常聪明,直到我的经理向我提出一些问题,例如:

  • 一次可以收到多少条消息?如果我们获得更多,会发生什么?
  • 如果处理时间太长,消息是排队还是会丢失?
  • 如果处理时间过长会怎样?

我们不能丢失消息,因为最后一个消息仍处理,我们无法建立,直到系统崩溃,因为它也没有内存。他想听到的(并且理所当然地)是某种验证,即有一种确定的方式来处理消息的“风暴”。不幸的是,我不知道该去哪里得到答案。我已经包含了我认为的相关代码。

所以:

  1. 有谁知道上述问题的答案?
  2. 我会在哪里进行一些研究,以找到这些答案和/或这类事情要遵循的一些模式?
  3. 我可以使用哪种工具来观察调试/性能分析的处理?
  4. 如果我在设计中犯了一个大错,我应该怎么做才能解决它(即引入队列,使用线程池等)?

    public void ReceiveCallback(IAsyncResult ar)
    {
        //Cast the item back to the listener
        UdpListener listener = (UdpListener)ar.AsyncState;
    
        //If we are supposed to be listening, then get the data from the socket
        //Listen is false during shutdown
        if (Listen)
        {
            //The try catch is placed inside the listen loop so that if there is an error in the processing it will 
            //recover and listen again. this may cause more exceptions but we can be sure that it will not
            // stop listening without us knowing
            try
            {
                //Address and port from the external system
                IPEndPoint ep = listener.EndPoint;
    
                //Get the data from the async read
                Byte[] receiveBytes = listener.Client.EndReceive(ar, ref ep);
    
                //Reset the socket to listen again
                listener.Client.BeginReceive(new AsyncCallback(ReceiveCallback), listener);
    
                //Execute the event to pass external components the message
                HeartbeatEventArgs hea = new HeartbeatEventArgs(DateTime.Now, ep, receiveBytes);
                OnHeartbeatReceived(hea);
    
                //Ack back to the external system
                HeartbeatAcknowledgement(new IPEndPoint(ep.Address, ep.Port), receiveBytes);
            }
            catch (Exception e)
            {
                log.Error(e.Message);
                //Reset the socket to listen again
    
            }
        }
    }
    
  5. listner只是UDPClient的包装器。如下:

    #region UdpClient Wrapper (UdpListener)
    /// <summary>
    /// UdpListener is used to control the asynchronous processing of a UDPClient object. 
    /// </summary>
    public class UdpListener
    {
        /// <summary>
        /// IPEndpoint on which to accept a connection. Usually set to "Any".
        /// </summary>
        public IPEndPoint EndPoint { get; set; }
        /// <summary>
        /// The socket based client object that is used for communication
        /// </summary>
        public UdpClient Client { get; set; }
    
        public UdpListener(int port)
        {
            EndPoint = new IPEndPoint(IPAddress.Any, port);
            Client = new UdpClient(EndPoint);
        }
    }
    #endregion
    

    谢谢,

    Dinsdale

1 个答案:

答案 0 :(得分:1)

如果丢失邮件是一个问题,那么UDP不适合你。 UDP仅保证如果消息到达,它将完成。它不保证消息顺序或交付。换句话说,如果客户端发送两条消息,您可能会无序接收它们,或者只接收第一条消息,或者只接收最后一条消息(或者根本不接收)。如果您需要保证交付和订单,请使用TCP(TCP附带自己的保证和陷阱)。

考虑到它可以处理的消息数量,您将有一个上限。如果您没有比到达时更快地处理消息,那么它们将在您的应用程序层或UDP网络层中排队。一旦网络缓冲区已满,您的网络接口就会开始丢弃消息。