2013-02-18 166 views
2

好的,这是我的第一个堆栈溢出问题,请随时提出更好的方法来问或我下次应该包括什么。大多数时候我可以谷歌来得到我的答案,但这一个是有点棘手......处理来自UdpClient.BeginReceive()的传入消息()

我正在写一个Windows应用程序在C#中侦听一个UDP端口,然后处理传入的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 
    
         } 
        } 
    } 
    

听者是只是一个包装围绕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

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

关于它可以处理多少个消息,你将有一个上限。如果您的邮件处理速度比达到的速度更快,那么它们将排队,无论是在应用层还是在UDP网络层。一旦网络缓冲区满了,您的网络接口就会开始丢弃消息。

+0

好的,这是一个开始!我知道UDP不保证任何可靠性。我无法控制使用的协议。如果收到我们不希望从应用程序端丢失的消息,那么问题就很简单。所以我应该在处理消息之前先清除我的网络缓冲区(即将消息放入队列?) – Dinsdale 2013-02-18 23:34:40

+0

这将是一个好方法。将消息移动到队列中,然后异步处理它们。您可以监控您的队列大小,以确保您有足够的容量。衡量的另一个指标是单个消息在队列中等待处理的时间。如果其中任何一个很大,那么你将不得不修改你的架构。 – 2013-02-18 23:51:43