技術共有

JavaEE 初級ネットワーク原則 2

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina


序文

TCP プロトコルには、接続、信頼性の高い伝送、バイト ストリーム指向、全二重などの特徴があります。信頼性の高い伝送はその中核部分です。


1. TCPヘッダー構造

図1
ここに画像の説明を挿入します
上図はTCPヘッダーの構造です。
(1) 送信元ポートと宛先ポートは、送信側と受信側を示すためのプログラムです。
(2) シーケンス番号と確認シーケンス番号は、後で導入される TCP の確認応答メカニズムに使用されます。
(3) データオフセット部の 4 ビットは、実際には TCP ヘッダの長さを示すために使用されます。4 ビットなので、最大数は 15 で表されますが、単位は 4 バイトであるため、最大長は 15 になります。 TCPヘッダーは60バイトです。
(4) UDP データ パケットの最大長は 64kb であり、非常に制限されていることは周知のとおりです。この状況を回避するために、TCP ヘッダーには 6 つの予約ビットが用意されており、TCP 機能が拡張された場合に使用できます。後で予約ビットを使用して表現されます。
(5) 6 バイトの英語の識別子は、後で紹介する TCP メカニズムに関連するため、ここでは紹介しません。
(6) チェックサムは、UDP のチェックサムと同じ機能を持ち、送信過程でデータが変更されていないかどうかを確認するためにも使用されます。
(7) ウィンドウについては、仕組みの導入時に説明します。
(8) 緊急ポインタについては後ほど紹介します。
(9) オプションの中には任意・任意のオプションもございます。

2. TCP の 10 のコアメカニズム

2.1 確認応答

TCP プロトコルは、信頼性の高い伝送という非常に重要な問題を解決する必要があります。いわゆる信頼性の高い送信とは、送信者が受信者にデータを 100% 送信できることを意味するものではありませんが、受信者が知っているかどうかを送信者に知らせるために最善を尽くします。
図2
ここに画像の説明を挿入します
図 2 に示すように、女神にメッセージを送信するたびに、女神は応答を返します。これは TCP の場合にも当てはまります。クライアントはデータ パケットを送信します。このとき、図 1 のパケットの ACK フラグが 1 に設定されます。
画像3
ここに画像の説明を挿入します
図 3 に示すように、女神に複数のメッセージを送信すると、女神の応答速度が異なるため、女神が私のガールフレンドであることに同意していると誤解しやすくなります。女神は迷子になると言っています。これがインターネットです。後者優先の問題は客観的に中国に存在します。明らかに、複数のデータ パケットをクライアントに送信し、クライアントが複数の応答データ パケットに応答する場合、どの応答が送信されたデータ パケットに対応するかを区別する必要もあります。この問題は、図 1 のシーケンス番号と確認シーケンス番号を使用して解決できます。 。
ここに画像の説明を挿入します
送信される各データ パケットにはシーケンス番号がありますが、確認シーケンス番号が存在しないか、これに応答するデータ パケットの ACK は 1 です。このとき、確認シーケンス番号フィールドは有効です。送信したデータパケットのシーケンス番号と応答 データパケットの確認シーケンス番号が対応しているため、誰が誰に応答したかが区別でき、前述のネットワークにおける後者優先の問題を解決できる。
実際の TCP データ パケットのシーケンス番号は、バイトごとに番号が付けられます。TCP ヘッダーのシーケンス番号の値は、たとえば、ペイロードの最初のバイトの番号です。ペイロード部の最初のバイトのバイト番号が 1、ペイロード長が 1000 バイトの場合、データ パケットの応答データ パケット ヘッダ内の送達確認シーケンス番号は 1001 になります。データ パケットに対応する応答データ パケットは、ペイロードの最後のバイトの番号が 1 増加します。実際には、1001 が返されると、送信された 1000 バイトのペイロードが受信されたことを意味し、図 4 に示すように、1001 以降のデータが要求されます。
図4
ここに画像の説明を挿入します
後続のデータ パケットが送信されると、シーケンス番号はインクリメントされますが、注意すべき点は、インクリメントされても、シーケンス番号は 0 または 1 から始まるわけではないことです。
確実な送信は主に「確認応答」メカニズムに依存することで実現できます。応答メッセージを通じて送信者に、すべてが順調に進んでいるかどうか、およびパケット損失が発生したかどうかを通知できます (送信プロセス中にデータがドロップされ、反対側に到達できない、つまり客観的なランダム イベント) 場合はどうすればよいでしょうか。

2.2 タイムアウト再送信

タイムアウト再送信は、ネットワーク内のパケット損失の問題に対処するために使用されます。
ここには主に 2 つの状況があります。
(1) 送信されたデータパケットが失われる
ここに画像の説明を挿入します
このとき、BはAのデータパケットを受信しない場合は応答パケットを送信せず、Aが待ち構えているイベントが一定の閾値を超えた場合、パケットロスの問題が発生したと判断し、データパケットを再送信します。
(2) 応答データパケットが失われる
ここに画像の説明を挿入します
A は応答データ パケットを受信しない場合でもデータ パケットを再送信しますが、この時点で B はデータ パケットを受信すると、同じデータ パケットを 2 つ受信することになります。特に、繰り返し転送が発生する転送などの問題の場合はそうです。
上記の問題に対して、TCP 受信側はシーケンス番号に従って受信データの重複を排除します。 TCP 層は重複の問題を考慮しません。重要なのは、データが何度再送信されても​​、アプリケーション層が重複したデータを読み取ることができないことです。
受信側オペレーティング システムのカーネルには、データ構造 (受信バッファ) があります。このデータ構造は、B がデータ パケットを受信し、複数の層を通過してトランスポート層に渡されるときに発生します。ブロッキング キューにデータを入力すると、キューはデータ パケットのシーケンス番号に基づいてデータが存在するかどうかを判断します (存在するということは、同じデータ パケットが受信され、一度データが読み取られたことを意味します)。アプリケーション層)、直接破棄されます。受信バッファのもう 1 つのポイントは、ネットワークにおける後者優先の問題を解決できることです。送信されたデータはシーケンス番号に従ってソートされ、アプリケーション層プログラムによって順番に消費されます。
ここに画像の説明を挿入します
上の図に示すように、受信バッファに到着するデータはシーケンス番号に従ってソートされます。これにより、最後に送信されたものから順に送信される問題だけでなく、重複したデータ パケットを受信する問題も解決されます。今回、再送信されたデータ パケットがシーケンス番号 500 で受信された場合、受信バッファの最小シーケンス番号は 1000 であり、アプリケーション プログラムによって 500 がすでに読み取られていることを意味するため、直接破棄されます。
パケット損失自体は確率的には小さいイベントですが、パケット損失の数が増加すると、ネットワークに大きな問題が生じます。再送信の回数が増えると、再送信間の時間間隔は長くなり続けます。これは、再送信が増えるとネットワークに問題があることを示し、頻繁な再送信はリソースを消費するためです。再送信回数がしきい値に達すると、RST フラグ ビットを 1 に設定してリセット メッセージが送信され、両端の中間ステータスがクリアされます。リセット メッセージに応答しない場合は、両端の接続が削除されます。
タイムアウト再送信は、確認応答を補足するものです。

2.3 接続管理

2.3.1 接続の確立: 3 ウェイ ハンドシェイク

図5
ここに画像の説明を挿入します
接続を確立するということは、図 5 に示すように、通信する両方の当事者が相手側の情報を保存することを意味します。
スリーウェイ ハンドシェイクの初回は、クライアントが開始する必要があります。具体的なプロセスを図 5 に示します。まず、クライアントは SYN パケットを送信します。つまり、ヘッダーの SYN フラグが 1 に設定されます。次に、サーバーは応答パケットを返します。応答パケットの ACK フラグと SYN フラグは次のとおりです。 ACK と SYN は両方とも 1 に設定されます。フラグ ビットを含むデータ パケットはオペレーティング システム カーネルによって同時に送信されるため、これらを一緒に送信してパフォーマンスを向上させることができます。最後に、クライアントは応答パケットをサーバーに送信し、3 ウェイ ハンドシェイクが完了します。このプロセス中に送信されるデータ パケットにはビジネス データは含まれません。
スリーウェイハンドシェイクの意味:
(1)石を投げて道を尋ねる
通信リンクがスムーズかどうかを確認する
(2) いくつかの重要なパラメータを交渉する
たとえば、送信されたデータ パケットのシーケンス番号
(3) 双方の送受信能力を確認する
なぜ3回握手するのですか?握手は4回でも2回でも大丈夫ですか?
4 方向ハンドシェイクは通常の機能には影響しませんが、2 方向ハンドシェイクではサーバーの送受信機能を完全に確認できません。
さらに、ここにはさらに 2 つの重要な状態が関係しています。1 つはリッスン状態です。これは、サーバーがこの時点でポートをバインドしており、クライアントが SYN パケットを送信するのを待っていることを意味します。分かりやすく、スリーウェイハンドシェイクが完了したことを意味します。接続が確立された後の状態です。

2.3.2 切断: 4 回手を振ります。

最初にクライアントによってのみ開始できる 3 ウェイ ハンドシェイクとは異なり、4 ウェイ ハンドシェイクはサーバーとクライアントの両方が開始できます。
図6
ここに画像の説明を挿入します
4 回手を振る具体的なプロセスを図 6 に示します。クライアント コードでsocket.close() メソッドが呼び出されるとき、またはプロセスが終了すると、サーバーはすぐに FIN 終了メッセージをサーバーに送信します。 ACK メッセージが返されますが、サーバー コードが返されるまで待つ必要があります。socket.close() などのコードを呼び出した後でのみ、FIN 終了メッセージをクライアントに送信できます。その後、クライアントは ACK メッセージをサーバーに送信します。 4回手を振るとプロセスが完了します。
ここで中央の ACK と FIN を組み合わせることはできません。ACK はシステム カーネルによって送信されるため、サーバーが FIN メッセージを受信するとすぐに送信されますが、FIN メッセージはサーバー側のコードが送信されるまで待つ必要があります。ソケットを実行します。これは close() の後に送信できますが、両者の間には時間差があります。ただし、特殊な状況では、ACK を遅延して送信し、FIN と一緒に送信できるように、この 2 つを組み合わせる方法があります。
さらに、4 つの Wave プロセスには 2 つの状態が含まれます。1 つは close_wait 状態で、もう 1 つは送信側の FIN メッセージを受信した後の状態です。送信者が受信者に送信した最後の ACK が失われるのを防ぐ必要があるため、接続はすぐには切断できません。受信者が FIN を再送信します。送信者が引き続きこの FIN を受信できるようにするために、この状態の時間は通常 2MSI (MSI: 両端でのデータ送信の最大時間)、通常は 2 分です。
受信側で多数の close_wait が見つかった場合は、close() メソッドが忘れられたことを意味します。多数の time_wait がサーバーで見つかった場合は、サーバーが多数のアクティブな TCP 切断をトリガーしたことを意味します。オペレーション。

2.4 スライディングウィンドウ

TCP は信頼性の高い送信を保証する必要がありますが、同時に、スライディング ウィンドウは効率を向上させるメカニズムです。これは実際には、信頼性を確保するために多くのパフォーマンスを犠牲にするため、データ送信速度を UDP よりも速くすることができないための方法です。
図7
ここに画像の説明を挿入します
図 7 に示すように、これはデータ送信のプロセスですが、データ パケットの送信と応答データ パケットの受信のプロセスは依然として比較的遅いです。
図8
ここに画像の説明を挿入します
図 8 に示すように、これはスライディング ウィンドウ メカニズムが導入された後です。一度に 1 つのデータ パケットではなく、複数のデータ パケットが送信されるため、返される応答データ パケットの待ち時間が重複します。 ACK を待たずに、バッチで送信されるデータの量がウィンドウ サイズになります。
図9
ここに画像の説明を挿入します
スライディング ウィンドウのプロセスを図 9 に示します。ウィンドウ サイズが 4 グループであると仮定すると、1 つのグループが ACK を受信すると、それを補うために新しいデータが送信されます。これはスライディング プロセスに相当します。送信者が 3001 の ACK を受信した場合は、1001 から 3001 までのデータが受信されたことを意味するため、ウィンドウは右に 2 スペース移動できます。
スライディング ウィンドウでパケット損失が発生した場合はどうすればよいですか? 次の 2 つの状況があります。
(1) 送信したデータパケットが失われる
ここに画像の説明を挿入します
送信されたデータグラムの特定のグループが失われた場合、多数のデータ グループをバッチで受信者に送信しても、受信した ACK の確認シーケンス番号は、送信者がデータグラムを再送信するまで、失われたグループの番号のままになります。たとえば、上の図のデータグラム 1001 ~ 2000 が失われた場合、その後複数のデータが送信されても​​、送信者が再送信して受信者がそれを受信するまで 1001 の ACK が返され、その後 7001 の ACK が応答されます。 。
(2) 応答ACKが失われる
ここに画像の説明を挿入します
応答 ACK が失われた場合は、他のデータ グループの ACK が返されるまで待つだけなので、心配する必要はありません。たとえば、上の図の 1001 の ACK が失われた場合は、それが返されます。 2001 年の次の ACK の送信者はそれを受信して​​います。また、次のデータの ACK が失われた場合も同様です。
前述のパケット損失の処理は、データ パケットが失われた場合でも、ギャップを埋めてデータを再送信するだけで非常に効率的です。ACK が失われた場合は、それを無視します。このような動作を高速再送信と呼びます。
タイムアウト再送信と高速再送信は、環境によって採用される戦略が異なります。TCP が少量のデータを送信する場合、短期間に大量のデータを送信する必要がある場合は、タイムアウト再送信がトリガーされます。高速再送信は、スライディング ウィンドウでのタイムアウト再送信の変形と同等です。

2.5 フロー制御

スライディング ウィンドウについて前述したように、ウィンドウ サイズは可変であり、ウィンドウのサイズを変更することで送信側の送信速度を制御できます。ウィンドウが大きいほど、単位時間あたりに送信されるデータが増加し、効率が高くなります。ウィンドウが小さいほど、単位時間あたりに送信されるデータが少なくなり、効率が低下します。もちろん、通常はできるだけ効率が高いことが望まれますが、高効率の前提条件は、送信側の送信が速すぎて受信側が処理できない場合、パケット損失が発生する可能性があります。これが「フロー制御」です。
ここに画像の説明を挿入します
上図に示すように、前述したようにカーネル内には受信バッファというデータ構造があり、受信側は受信バッファの空き領域のサイズをウィンドウサイズとして返します。以前の TCP ヘッダーには 16 ビットのウィンドウ サイズ フィールドがあり、ACK を使用してこの情報を保存および返します。ウィンドウ サイズ フィールドは ACK でのみ有効です。
ここに画像の説明を挿入します
上の図に示すように、ACK はフロー制御の目的を達成するためにウィンドウのサイズを返します。ウィンドウ サイズが 0 に戻ると、送信者はビジネス データを含まないプローブ メッセージを定期的に送信して、ACK をトリガーしてフロー制御の目的を達成します。バッファの空き容量があるかどうか。

2.6 輻輳制御

輻輳制御はフロー制御と非常に似ており、両方のメカニズムがスライディング ウィンドウと組み合わされています。
ここに画像の説明を挿入します
上の図に示すように、ネットワーク内のリンクは非常に複雑で、リンク上のノードによって送信側の速度が制限される可能性があります。輻輳制御の考え方は、中間構造がどれほど複雑であってもそれを全体として扱い、実験を通じて最適なウィンドウ サイズを見つけることです。
ここに画像の説明を挿入します
上図は輻輳制御プロセスです。ネットワークの輻輳状況がわからないため、最初は比較的小さなウィンドウ サイズ (スロー スタート) で試してください。その後、ウィンドウ サイズは急激に増加します。一定のしきい値を超えると、ウィンドウは直線的に増加し始めます。ウィンドウがある程度大きくなると、パケット ロスが発生します。このとき、ウィンドウのサイズを縮小するには次の 2 つの方法があります。
(1) 直接下まで縮小し、スロースタートの先頭に戻り、前のプロセスを繰り返します(すでに放棄されています)
(2) 半分に縮小し、その後直線的に拡大する(実際に使用した方法)
輻輳制御では、パケット損失が多い場合はウィンドウ サイズを減らし、パケット損失がない場合はウィンドウ サイズを増やします。

2.7 応答の遅れ

名前が示すように、応答の遅延は、ACK を返す前にしばらく待つことを意味します。ACK の応答が遅延すると、受信側が受信バッファ内のデータを消費する時間が長くなり、ウィンドウ サイズの問題も伴います。空きバッファのサイズが増加し、ACK によって返されるウィンドウ サイズが増加し、送信者はより多くのデータをバッチで送信できるようになります。
遅延応答には次の 2 つの方法があります。
(1) 一定の時間による遅延を指定する
(2) 受信データ量に応じて
上記 2 つの戦略は組み合わせて使用​​されます。

2.8 ピギーバック応答

実は、伝送効率を高めるための仕組みとして、ピギーバック応答は以前から登場していました。これは、スリーウェイ ハンドシェイクで同じデータ パケットを使用して ACK と SYN が返される場合です。 Four Waves と同様の状況は、ACK と FIN が異なるタイミングで送信されるため、相乗り応答を行うことができません。ただし、遅延応答では、送信者に ACK をそれほど早く送信する必要がありません。 2 つの FIN と組み合わせて、応答に便乗することで 1 つの送信に結合できます。

2.9 バイトストリーム指向

バイト ストリーム指向は、TCP のメカニズムの 1 つであり、パケット スティッキングの問題は、その特性により、異なるアプリケーション層のデータ パケット間の境界を区別できないことによって引き起こされます。複数のバイトを読み取ると 1 バイトを読み取ることもできるため、この問題が発生しやすくなります。
上記の粘着性バッグの問題には 2 つの解決策があります。
(1) セパレータを使用する
リクエストパケット内に存在しないシンボルであれば、任意のシンボルを使用できます。
(2) データパケットの長さに同意する
ただし、ほとんどの場合、Java プログラマは TCP を直接使用せず、http などの既製のプロトコルを使用するか、protobuffer や dubbo などのツールに基づいてネットワーク通信を実装することで、スティッキー パケットの問題を内部的に解決しています。失った。

2.10 異常事態

(1) 通信の両端で、一方のプロセスがクラッシュしました。
オペレーティング システムは 4 つのウェーブを完了し、PCB をウェーブします。
(2) あるホストをシャットダウンする(通常の処理)
1 つ目の可能性は、オペレーティング システムが 4 つのウェーブを完了したことです。2 つ目の可能性は、受信者が FIN を送信した後に一方的に接続を削除したことです。それらはすべてシャットダウンされるため、保存されている情報(メモリ)は自然に失われます。
(3) あるホストの電源が切れた。
電源オフのホストがサーバーの場合、クライアントが送信したデータパケットは ACK なしで再送信され、複数回再送信しても結果が得られない場合、接続は削除されます。
電源オフのホストがクライアントであり、サーバーがデータ パケットを長期間受信していない場合、サーバーはペイロードなしでハートビート パケットを定期的に送信します。クライアントが正常であれば、ACK を返します。 ACK を連続して送信してもクライアントから応答がない場合は、クライアントがダウンしていると考えられ、接続情報が削除されます。
さらに、TCP はハートビート パケットを実装しますが、このハートビート パケットを通じてクライアントがダウンしていることを確認するまでに数分かかることがよくあります。実際の開発では、アプリケーション層のハートビート パケットは、より高い頻度でより短い周期 (秒レベル/ミリ秒レベル) で送信され、B->A はポンで応答します。デバイスがハングした場合は、問題をすぐに見つけることができます。
(4) ネットワークケーブルが抜けている
基本的に、これは 3 番目のケースであり、送信者が ACK を受信しない場合はタイムアウトして再送信し、その後 RST を送信し、受信者がデータ パケットを受信しない場合は一方的に接続を削除します。 ACK を受信しない場合は、単にハートビート パケットを送信します。

2.11 補足

TCP ヘッダー構造には、言及されていない 2 つのフラグ ビットがあります。つまり、PSH と PSH は、相手側にできるだけ早く応答を返すよう促します。 URG は、TCP パケット ヘッダーの緊急ポインタ フィールドに関連付けられており、TCP 帯域外データ送信を制御するために一緒に使用されます。
帯域外データ送信とは、ビジネス データに加えて、TCP 自体の動作メカニズムを制御するために使用されるいくつかの特別なデータ パケットがあることを意味します。