3

サーバーと、クライアントがサーバーにパケットの束を送信するクライアント アプリケーションがあります。使用されるプロトコルは UDP です。クライアント アプリケーションは新しいスレッドを生成して、パケットをループで送信します。サーバー アプリケーションは、ループ内でパケットを待機する新しいスレッドも生成します。

これらのアプリケーションは両方とも、転送の進行状況に合わせて UI を更新し続ける必要があります。UI を適切に最新の状態に保つ方法は、この質問で解決されました。基本的に、サーバー アプリケーションとクライアント アプリケーションの両方が、ループの反復ごとにイベント (以下のコード) を発生させ、進行状況に合わせて UI を更新し続けます。このようなもの:

private void EVENTHANDLER_UpdateTransferProgress(long transferedBytes) {
    receivedBytesCount += transferedBytes;
    packetCount++;
}

receivedBytesCount各アプリケーションのタイマーにより、とからの最新情報で UI が更新されpacketCountます。

クライアント アプリケーションにはまったく問題はなく、すべてが期待どおりに機能しているように見え、パケットが送信されるたびに UI が適切に更新されます。サーバーが問題です...

転送が完了するreceivedBytesCountpacketCount、送信されたバイトの合計サイズにも、クライアントが送信したパケットの数にも一致しません。ちなみに、各パケットのサイズは 512 バイトです。Socket.ReceiveFrom()サーバー アプリケーションは、からの呼び出しが返された直後に受信したパケットをカウントしています。そして、何らかの理由で、必要なすべてのパケットを受信して​​いないようです。

パケットが実際に宛先に到着し、再送信が実行されないことを保証しない UDP を使用していることはわかっているため、パケット損失が発生する可能性があります。しかし、私の質問は、実際にこれをローカルでテストしているので、サーバー/クライアントの両方が同じマシン上にあるのですが、なぜこれが起こっているのでしょうか?

Thread.Sleep(1)クライアント送信ループに (15 ミリ秒の一時停止に変換されるように見える) を配置すると、サーバーはすべてのパケットを受信します。これをローカルで行っているため、クライアントは (呼び出しなしで) パケットを非常に高速に送信しているためSleep()、サーバーは追いつくことができません。これは問題ですか、それとも別の場所にある可能性がありますか?

4

1 に答える 1

3

「クライアントの送信ループに Thread.Sleep(1) (15ms の一時停止に変換されるようです) を配置すると、サーバーはすべてのパケットを受信します」

ソケット バッファがいっぱいになり、スタックがメッセージを破棄しています。UDP にはフロー制御がないため、タイトなループで膨大な数のデータグラムを送信しようとすると、一部が破棄されます。

sleep() ループを使用して (うーん!)、何らかの形式のフロー制御を UDP の上に実装し、何らかの形式の非ネットワーク フロー制御を実装します (たとえば、非同期呼び出し、バッファ プール、スレッド間通信を使用)。 、またはフロー制御が組み込まれた別のプロトコルを使用します。

ネットワークスタックが消化するよりも速く物をシャベルでシャベルした場合、時折スローアップしても驚かないでください.

于 2012-04-10T13:59:56.010 に答える