4

UDP を使用して同じプログラムの他のインスタンスと通信するネットワーク ソフトウェアがあります。さまざまな理由から、ここでは UDP を使用する必要があります。

最近、UDP 経由で大量のデータを送信する際に問題が発生し、メッセージを小さなデータ チャンクに分割するための断片化システムを実装する必要がありました。これまでのところうまくいきましたが、大量のデータ チャンクを送信する必要があるときに問題が発生しました。

私は次のアルゴリズムを持っています:

  1. メッセージを小さなデータ チャンク (約 1500 バイト) に分割します。
  2. データ チャンク リストを反復処理し、それぞれについて、次を使用して送信します。sendto()

しかし、大量のデータ チャンクを送信すると、受信者は最初の 6 つのメッセージしか取得しません。6 番目を逃して 7 番目を受け取ることもあります。場合によります。

とにかく、sendto()常に成功を示します。これは、ループバック インターフェイス (127.0.0.1) 経由でソフトウェアをテストすると常に発生しますが、LAN ネットワーク経由では発生しません。

std::cout << "test" << std::endl;間に何かを追加するとsendto()、すべてのフレームが受信されます。

UDP ではパケット損失が許容されることと、多くの理由でフレームが損失する可能性があることを認識しています。これは、データ チャンクを送信する速度に関係していると思います。

ここで正しいアプローチは何でしょうか?

  • 何らかの確認応答メカニズム (TCP など) を実装するのはやり過ぎのようです。
  • 間に任意の待機時間を追加するのsendto()は見苦しく、おそらくパフォーマンスが低下します。
  • (可能であれば) 受信機の UDP 内部バッファーを増やしますか? これが可能かどうかさえわかりません。
  • 他の何か?

ここであなたのアドバイスが本当に必要です。

ありがとうございました。

要求に応じた追加情報

UDP を使用しなければならない理由は、いくつかの制約があるためです。

  1. TCP は NAT トラバーサルでうまく機能しません(少なくとも特定の構成がなければ)
  2. 一部のメッセージが失われる可能性があります。できない人もいます。
  3. メッセージの配信順序は重要ではありません。
4

7 に答える 7

2

UDP を信頼できないと呼ぶのは、TCP をすべてのネットワーク障害の万能薬にしようとする単純化です。同様に、TCP を信頼できるものとして定義することも誤りです。確かに TCP にはデータが確実に転送されるようにするメカニズムがありますが、UDP パケットの到着の失敗を引き起こす障害の多くは、TCP の失敗の原因にもなります。

たとえば、ハードウェア ネットワーク障害は、UDP パケットと TCP パケットに同じ影響を与えます。障害が続く場合、TCP は UDP ほど確実に通過しません。実際、この場合、失われた原因をより長く完了しようとするという点で、TCP には欠点があります。インターネット経由でデータを送信する場合、パケットが送信されるルートを事前定義できないため、TCP にはいくつかの利点があります。ただし、LAN 経由でデータを送信する場合は、UDP で十分です。パケットが宛先に届かない場合は、修正が必要なハードウェア障害を示しています。ここでは TCP は役に立ちません。

また、プロトコルを選択するときは、データも理解する必要があります。センサーからの読み取り値など、データが一時的なものである場合は、UDP over TCP を使用する方がはるかに理にかなっています。この状況でパケットが失われたとしても、別のパケットが間もなく到着するため、ほとんど影響はありません。一方、TCP はバックオフして再試行します。データが到着する頃には、すでに古くなっています。

真実は、TCP がデータのストリーミング用に設計されたということです。この状況では、すべてのデータ パケットが確実に順序どおりに到着することが重要です。UDP はパケット データ用であり、このタイプのデータ用です UDP は、信頼性が高く、オーバーヘッドが少なく、ネットワーク障害の検出と回復が迅速であるため、完全に受け入れられます。

于 2012-01-17T18:46:30.583 に答える
2

6 ~ 7 個のパケットを送信しただけでループバック インターフェースを介してパケットが失われている場合は、受信バッファーが小さすぎる可能性があります。SO_RCVBUF オプションを使用して、setsockoptでサイズを増やすことができます。ただし、1500 バイトを送信している場合、これが実際に問題である場合は、受信バッファーが約 9K (または 8K の可能性が高いですが、デフォルトではかなり小さいようです) しかないことを意味します。Windows のデフォルトの受信バッファは 16K だと思います。

受信バッファーを増やすことが役立つと仮定しても、他の人が言及した問題に対処する必要があります。考慮すべき他のいくつかのことは、断片化を避けるために最大パケット サイズを動的に決定しようとすることです。また、ACK 間で送信されるパケット サイズとパケット数を手動で構成できるようにすることも理にかなっている場合があります。

于 2010-04-18T13:43:28.677 に答える
1

確認応答と再送信を実装する必要があります。たとえば、N パケットごとに ack を要求し、N パケットを再送信バッファーに保持します。

(おそらくrudpからいくつかのアイデアを得るか、 UDP を介してIlを実装することができます)

UDP は信頼性が低く、フロー制御も提供しません。簡単に言うと、特にデータを高速で送信すると、パケットが時々失われます。十分なスペースがない場合、カーネルまたは間にあるルーター/スイッチはパケットをドロップします。それを防ぐために使用できる魔法はほとんどありません。発生する。

于 2010-04-18T12:55:10.457 に答える
1

確認メカニズムを実装することは、まさにあなたがしなければならないことのように思えます。こうすることで、一度に「飛行中」のパケットが N 個を超えないようにすることができ、長時間にわたって未確認のパケットを再送信できます。

于 2010-04-18T12:45:54.670 に答える
0

TCP はまさにこの種の問題を解決するために存在します。TCP がオプションではないのはなぜですか? 同じ問題をすべて解決しなければならず、最終的には同じ解決策にたどり着きますが、何十年にもわたる TCP スタックの研究、開発、およびデバッグの恩恵を受けていません。

本当に UDP を使用しなければならない場合、最初に尋ねるべき質問は、TCP の保証に関して何をあきらめる気があるかということです。順不同でパケットを受信して​​もよろしいですか? パケットの一部が失われても問題ありませんか? 重複パケットの到着を処理できますか? これらの質問に対する答えが、うまくいけば設計につながります。

あなたの詳細を知らなければ、「これをやれば大丈夫だ」という簡単な質問に答えることはできません。

于 2010-04-18T12:48:46.430 に答える
0

UDP はデータグラムを送信するため、信頼性が低くなります。

TCP はデータ ストリームを送信し、信頼性があります。

あなたが望むものはデータグラムベースのようですが、信頼できます。したがって、それを実現するには、UDP または TCP のいずれかに何かを構築する必要があります。まさにそれを提供するUDP上に構築された完全なプロトコル仕様があると確信しています。それらを見つけて実装するだけです。

于 2010-04-18T13:01:07.103 に答える