5

次のコードを検討してください。

class UPDServer {

    //start listener
    public void start() {
        UdpClient listener = new UdpClient(this._porta);
        IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 10000);

        State s = new State();
        s.listener = listener;
        s.ipEndPoint = ipEndPoint;

        // begin to listen again
        listener.BeginReceive(new AsyncCallback(ReceiveCallback), s);

   }

 //receive data
   public void ReceiveCallback(IAsyncResult ar)
   {
      // we got data
      State s = (State)(ar.AsyncState);

      Byte[] received = e.escuta.EndReceive(ar, ref e.ipEndPoint);
      string text = ""; = Encoding.ASCII.GetString(received);
      // ... do somenthing with text

      // begin to listen again
      s.listener.BeginReceive(new AsyncCallback(ReceiveCallback), e);
   }
}

上記のコードでは、EndReceive と次の BeginReceive の間に誰もリッスンしていない時間帯があります。この時間帯にメッセージがあると、メッセージは失われると思います。

まあ、何らかのバッファがあると思いますが、それでも、誰もメッセージをリッスンしていない時間帯にバッファがいっぱいになると、メッセージが失われます。

同じエンドポイントでBeginReceiveを数回呼び出すことでこれを非常に簡単に解決できると誰かが言ったことを覚えているので、これを試しました:

   for( int x = 0; x < 5;x++) {
      escuta.BeginReceive(new AsyncCallback(ReceiveCallback), e);
   }

奇妙なことに、同じソケットで begin receive を呼び出してもエラーはスローされませんが、メッセージが受信されるたびに、5 つすべての beginReceive が起動し、5 つすべてが同じメッセージを受け取ります。

コードを改善する方法はありますか?

4

1 に答える 1

2

まず、UDP を使用するときにすべてのデータを取得できるという保証はないため、コード/プロトコルをフォールト トレラントにする必要があります。

処理が非常に集中的で、膨大な量のデータが殺到することが予想される場合を除き、別のことを行う必要はおそらくありません。エラー検出コードを追加するだけで、コードが対応できていないかどうかがわかります。

ただし、受信ループを高速に保つ必要がある場合は、データを受信したら、別のスレッドが処理するキューにデータをコピーして、すぐに読み取りを再開できるようにします。または、状況によっては、end-receive を記述して、複数のパケットが連続して受信された場合に再入可能になるように処理できる場合があります。

于 2012-05-10T19:17:15.790 に答える