最初の事実:
UDP には、パケット ヘッダーのビット 40 から始まる 16 ビットのチェックサム フィールドがあります。これには、(少なくとも) 2 つの弱点があります。
- チェックサムは必須ではありません。0 に設定されたすべてのビットは「チェックサムなし」として定義されます。
- これは厳密な意味で16 ビットのチェックサムであるため、検出されない破損の影響を受けやすくなっています。
つまり、環境によっては、UDP の組み込みチェックサムが十分に信頼できる場合とそうでない場合があります。
第二の事実:
トランスポートに沿ったデータ破損よりもさらに現実的な脅威は、パケット損失の並べ替えです。USP は次のことについて保証しません。
- (最終的に)到着するすべてのパケット
- パケットが送信されたのと同じ順序で到着する
実際、UDP には、単一のパケットよりも大きなペイロードを処理するための組み込みメカニズムがまったくありません。これは、そのために構築されていないという事実に起因します。
結論:
追加の手段なしで受信したパケットを次々と追加すると、非常に好ましい環境を除くすべての環境で送信ストリームとは異なる受信ストリームが生成され、直接ファイル転送に最適なプロトコルとは言えません。
UDP を使用してファイルを転送したい、または使用しなければならない場合は、TCP には不可欠であるが UDP には不可欠ではない部分をアプリケーションに組み込む必要があります。ただし、これにより、TCP の再実装が不十分になる可能性が高いということわざがあります。
成功した実装には、多くのピア ツー ピア ファイル共有プロトコルが含まれます。これらのプロトコルでは、接続の中断やパケットの損失に対する保護、またはフィルタを無効にするか軽減するために、アプリケーションの機能の一部として並べ替えを行う必要があります。
実装の推奨事項:
私たちにとってうまくいったのは、チャンク ウィンドウの実装です。ペイロードは固定された便利な長さのチャンクに分割され (1023 バイトを使用しました)、N 個のチャンクのステータス配列が送信側と受信側で保持されます。
送信側:
- そのようなチャンク、ストリーム内のそのシーケンス番号 (複数回)、およびチェックサムまたはハッシュを含む UDP メッセージが開始されます。
- ステータス配列は、タイムスタンプでこのチャンクを「送信済み/保留中」としてマークします
- 完全なステータス配列 (送信ウィンドウ) が消費されると、送信が停止します
受信側:
- 受信したパケットはチェックサムに対してチェックされます。
- 破損したパケットは、シーケンス番号のすべてのコピーが一致する場合は否定的に確認され、そうでない場合はドロップされます
- OK パケットはステータス配列で「受信済み/保留中」としてタイムスタンプ付きでマークされます
- ACK パケットを満たすのに十分なチャンクが受信された場合、または最も古い「受信/保留中」のタイムスタンプが古すぎる (数ミリ秒から数 100 ミリ秒) 場合、確認応答は ack パケットを送信することによって機能します。
- Ack パケットにはチェックサムが必要ですが、順序付けは必要ありません。
- 確認応答が送信されたチャンクは、ステータス配列にタイムスタンプを付けて「確認/保留中」としてマークされます
送信側:
- Ack パケットを受信してチェックし、破損したパケットをドロップします
- ack が受信されたチャンクは、ステータス配列で「ack/done」としてマークされます
- ステータス配列の最初のチャンクが「ack/done」とマークされている場合、ステータス配列は、最初のチャンクが再び完了しないまでスライドアップします。
- これにより、送信される 1 つ以上の未送信チャンクが解放される可能性があります。
- ステータスが「送信済み/保留中」のチャンクの場合、元のチャンクが失われた可能性があるため、タイムスタンプのタイムアウトにより、このチャンクの新しい送信がトリガーされます。
受信側:
- チャンク i+N (N はウィンドウ幅) を受信すると、チャンク i に ack/done のマークが付けられ、受信ウィンドウが上にスライドします。受信ウィンドウからスライドするすべてのチャンクが「ack/pending」としてマークされていない場合、これは回復不能なエラーを構成します。
- ステータスが「ack/pending」のチャンクの場合、元の ack メッセージが失われた可能性があるため、タイムスタンプのタイムアウトにより、このチャンクの新しい ack がトリガーされます。
明らかに、送信ウィンドウがファイルの最後をスライドする場合、チャンク N+i を送信せずに ack の受信を通知するために、送信側から特別なメッセージ タイプが必要です。存在しますが、ペイロードはありません。