2

わかりました、これは私の最初のスタック オーバーフローの質問です。質問のより良い方法や、次回は何を含める必要があるかをお気軽に提案してください。ほとんどの場合、Google で答えを得ることができますが、これは少しトリッキーです...

UDP ポートをリッスンし、着信 UDP メッセージを処理する Windows アプリケーションを C# で作成しています。より具体的には、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
    
            }
        }
    }
    

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

ありがとう、

ディンズデール

4

1 に答える 1

1

メッセージの損失が懸念される場合は、UDP は適していません。UDP は、メッセージが到着した場合に完全であることのみを保証します。メッセージの順序や配信を保証するものではありません。言い換えると、クライアントが 2 つのメッセージを送信した場合、それらを順不同で受信するか、最初のメッセージのみ、または最後のメッセージのみ (またはまったく受信しない) を受信する可能性があります。配信と順序を保証する必要がある場合は、代わりに TCP を使用してください (TCP には独自の保証と落とし穴があります)。

処理できるメッセージ数には上限があります。メッセージが到着するよりも速く処理されていない場合、メッセージはアプリケーション層または UDP ネットワーク層のいずれかでキューに入れられます。ネットワーク バッファがいっぱいになると、ネットワーク インターフェイスは単純にメッセージの破棄を開始します。

于 2013-02-18T23:26:18.343 に答える