好的,這是我的第一個堆棧溢出問題,請隨時提出更好的方法來問或我下次應該包括什麼。大多數時候我可以谷歌來得到我的答案,但這一個是有點棘手......處理來自UdpClient.BeginReceive()的傳入消息()
我正在寫一個Windows應用程序在C#中偵聽一個UDP端口,然後處理傳入的UDP消息。更具體地說,我使用UDPClient
類,並使用BeginReceive方法進行偵聽。接收回調反過來激發它自己的消息接收事件,然後再次重置UDP客戶端。這個「MessageReceived」事件隨後由處理器對象處理。
我認爲這是所有非常聰明,直到我的經理提出了一些問題,以我如:
- 這多少信息可以接收一次?如果我們獲得的不僅僅是這些,會發生什麼
- 如果處理時間過長,消息是排隊還是會丟失?
- 如果處理時間過長會發生什麼?
我們不能丟失消息,因爲最後一個仍在處理中,我們不能建立起來,直到系統崩潰,因爲它的內存不足。他希望聽到的(以及理所當然的)是某種驗證,即有一種確定的方式來處理消息的「風暴」。不幸的是,我不知道該怎麼去得到答案。我已經包含了我認爲是下面的相關代碼。
所以:
- 有誰知道答案,上述問題?
- 我在哪裏可以做一些研究來找到這些答案和/或一些模式以遵循這種事情?
- 我可以使用哪種工具來觀察調試/性能分析的處理過程?
如果我在設計中犯了一個大錯誤,我應該怎麼做才能對它進行排序(即引入一個隊列,使用線程池等)?
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
好的,這是一個開始!我知道UDP不保證任何可靠性。我無法控制使用的協議。如果收到我們不希望從應用程序端丟失的消息,那麼問題就很簡單。所以我應該在處理消息之前先清除我的網絡緩衝區(即將消息放入隊列?) – Dinsdale 2013-02-18 23:34:40
這將是一個好方法。將消息移動到隊列中,然後異步處理它們。您可以監控您的隊列大小,以確保您有足夠的容量。衡量的另一個指標是單個消息在隊列中等待處理的時間。如果其中任何一個很大,那麼你將不得不修改你的架構。 – 2013-02-18 23:51:43