4

UDP の不安定性は物理層の特性であるという印象を受けましたが、そうではないようです。

一連のパケットに分割された UDP 経由でメッセージを送信しようとしています。メッセージの識別と並べ替えは暗黙的に行われます。

同じコンピューターで実行される 2 つのアプリでこの方法をテストし、スムーズに実行されることを期待しました。ただし、データ転送は完全に同じマシン上の 2 つのプログラム間で行われたにもかかわらず、パケットの損失が頻繁に発生していました。損失も非常にランダムなようです。メッセージ全体が通過する場合もあれば、通過しない場合もあります。

さて、同じマシンでも損失が発生するという事実は、私がそれを正しく行っているかどうか疑問に思います。

もともと、メッセージのすべてのピースをシングルショットで非同期に送信し、1 つのピースの完了を待たずに次のピースを送信していました。

次に、前のメッセージの完了ルーチン内から次のメッセージを送信しようとしました。これにより、パケット損失率は改善されましたが、完全に防止されたわけではありません。

ピースの間に一時停止 (Sleep(...)) を追加すると、100% 動作します。

編集: 答えが示唆したように:パケットは単に送信されるのが速すぎて、OS は最小限のバッファリングを行います。それは論理的です。

では、確認応答をシステムに追加して再送信するのを防ぎたい場合 (その場合は TCP を使用するだけで済みます)、どうすればよいでしょうか? データレートをより高いレベルに落とすことなく、パケット損失率を改善する最善の方法は何ですか?

編集2: 問題は、バッファが利用できないというよりも、正確にバッファオーバーフィルではない可能性があることに気づきました。私は非同期WSARecvFromを使用して受信しています。これは、私が理解しているように、デフォルトのOSバッファをオーバーライドするバッファを取ります。データグラムが受信されると、バッファに送られ、バッファがいっぱいかどうかにかかわらず、完了ルーチンが呼び出されます。

その時点で、完了ルーチン内から WSARecvFrom が再度呼び出されるまで、受信データを処理するためのバッファはまったくありません。

問題は、ある種のバッファープールを作成する方法があるかどうかです。そのため、別のバッファーが処理されている間にデータをバッファーに入れることができますか?

4

7 に答える 7

6

あなたの場合、受信プロセスがパケットを読み取るには、パケットの送信が速すぎます。O/S は、パケットの破棄を開始する前に、特定の数の受信パケットのみをバッファリングします。

これを回避する最も簡単なメカニズムは、受信プロセスが最小限の ACK パケットを送り返すようにすることですが、送信プロセスは、数ミリ秒以内に ACK を受信して​​いなくても処理を続行します。

編集 - 基本的に、UDP は「ファイア アンド フォーゲット」です。TCP のようなフィードバック メカニズムはプロトコルに組み込まれていません。伝送速度を調整する唯一の方法は、遠端がストリーム全体を受信して​​いないことを知らせることです。RFC 2309も参照してください。


Re: パケット シーケンス - 再順序付けは物理層が原因で発生しません。通常、これは IP ネットワークが「回線交換」ではなく「パケット交換」であるためです。

つまり、各パケットはネットワークを介して異なるルートをたどる可能性があり、これらの異なるルートには異なる遅延がある可能性があるため、パケットは順不同で到着する可能性があります。

実際、最近では、物理層のエラーが原因でパケットが失われることはほとんどありません。パケットは、制限されたスループット パイプにそのパイプが対応できるよりも高いレートで送信されるため、失われます。バッファリングは、パケット フロー レートを平滑化することでこれを支援できますが、バッファがいっぱいになると振り出しに戻ります。

于 2009-05-20T13:13:27.517 に答える
3

OS バッファの問題を回避するには、レート制御システムを実装する必要があります。閉ループ (受信者が ACK とそのバッファーに関する情報を送り返す) または開ループ (送信者が速度を落とします。つまり、保守的である必要があります) のいずれかです。

UDP が両方を実装するための準標準プロトコルがあります。RBUDP ( Reliable Blast UDP ) が思い浮かびますが、他にもあります。

于 2009-05-20T13:55:42.520 に答える
2

UDPを使用している場合、私が知る限り、パケット損失を検出する唯一の方法は、何らかのフィードバックを伴うことです。スループットがかなり安定しているネットワークを使用している場合は、データのバーストを送信し、受信者が応答するのを待って、受信したバーストからのパケット数を通知するトレーニング期間を実行できます(つまり、受信者をカウントし、タイムアウト後、取得した番号で応答します)。次に、制限に達するまでバーストごとのデータ量を増やし、念のために少し下げます。

これにより、初期評価期間後の問題が回避されますが、ネットワーク/受信プロセスの負荷が変化しない場合にのみ機能します。

私は以前にPythonでUDPクライアントを作成しましたが、重大なパケット損失を見つけたのは、受信プロセスの入力バッファーが小さすぎる場合だけでした。その結果、システムに大きな負荷がかかると、バッファがサイレントにオーバーフィルするため、パケット損失が発生します。

于 2009-05-20T13:46:36.967 に答える
1

WSA_FLAG_OVERLAPPEDにフラグを渡すと、複数回WSASocket()呼び出して、WSARecvFrom()複数の受信 I/O 要求をキューに入れることができます。そうすれば、完了ルーチンが別の I/O 要求をキューに入れる前であっても、次のパケットを受信するために使用できる別のバッファーが既に存在します。

これは、必ずしもパケットをドロップしないという意味ではありません。プログラムが十分な速度で十分なバッファーを提供しない場合、またはそれらを処理して再キューイングするのに時間がかかりすぎる場合は、追いつくことができず、何らかのレート制限が役立つ場合があります。

于 2009-05-21T05:27:39.523 に答える
0

あなたは何か間違ったことをしなければなりません。パケットを失う唯一の方法は、1)信頼性の低いネットワーク2)受信プログラムで処理するには速すぎるデータを送信していることです。3)UDPの最大メッセージサイズよりも大きいメッセージを送信しています。4)ネットワーク内の各デバイスには最大メッセージサイズ(MTU)があるため、制限を超えている可能性があります。

ケース#1の場合、同じマシンで送信しているため、ネットワークも関与していないため、100%信頼できるはずです。ネットワークカードが2枚あるとは言わなかったので、これは問題ではないと思います。

ケース2の場合、通常、データのドロップを開始する前に、大量のデータを送信する必要があります。あなたの説明から、それはケースのように聞こえません。

ケース3の場合、すべてのメッセージがこの制限を下回っていることを確認してください。

ケース#4の場合、UDPの最大メッセージサイズを満たしていれば問題ないはずですが、データが通過するMTUが小さい古いハードウェアまたはカスタムデバイスが存在する可能性があります。その場合、それらのパケットはサイレントにドロップされます。

私は多くのアプリケーションでUDPを使用してきましたが、非常に信頼性が高いことが証明されています。メッセージの受信にMFCを使用していますか?もしそうなら、あなたはあなたが知っておく必要のあるいくつかの問題を明確に述べているので、あなたは非常に注意深くドキュメントを読む必要があります、しかしほとんどの人はただそれらをざっと見ています。メッセージが機能しない理由を人々が理解できなかったとき、私はそれらのグロスオーバーのかなりの数を修正しなければなりませんでした。

編集:あなたはあなたのパケットが暗黙的に並べ替えられると言います。暗黙の並べ替えが実際に正しく機能していることを確認することから始めるかもしれません。それはあなたの問題の最も可能性の高い候補のようです。

編集#2:ネットワークモニターを使用してみましたか。マイクロソフトは、おそらく役立つネットワークモニターと呼ばれる無料のプログラムを持っています(または少なくとも以前は使用していました)。

于 2009-05-20T13:43:58.703 に答える
0

あなたのマシンのIP層はあなたが送ったほど速く送信できないのではないかと思います。

おそらく、プロトコルがパケットのドロップを許可しているため、他の目標(パケットをできるだけ速く送信する)が他の方法では達成できない場合です。

異なる結果は、マシン上の他のトラフィックまたはCPUを食べるプロセスによって説明される可能性があります。テスト中に、トップ(unix)またはプロセスエクスプローラー(nt)で監視しましたか?

于 2009-05-20T13:19:43.603 に答える
-1

OS のバッファリングが、頻度の低いコンテキスト スイッチに対応できていないようです。つまり、低レベルの送信には、より頻繁なコンテキスト スイッチが必要です。低レベルの送信バッファ サイズを最適化する方法があるかどうかを確認します。

于 2014-02-11T04:27:49.327 に答える