2013-02-18 70 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

相關問題