Linux の章 [16]: トランスポート層プロトコル <序文>

目次

1. ポート番号についてもう一度話します。

1. ポート番号の定義

2. ポート番号範囲分割

(1) 合計 2^16 個のポートがあります

(2)ウェルノウンポート番号を知る(Well-Know Port Number)

3. ポート番号とプロセスはKV関係です

4.ネット統計

(1) 例 1: n はエイリアスの表示を拒否し、表示可能な数値はすべて数値に変換されます。

(2) 例 2: l Listening (モニタリング) でサービスの状態のみを一覧表示する

(3) 例 3: p は、該当するリンクを確立しているプログラムの名前を表示します。

5.ピドフ

2. UDPプロトコル

1. UDPプロトコル終了フォーマット

(1) UDPプロトコルの構造

(2) ヘッダーはビット セグメントを含む構造です。

(3) ヘッダー追加の本質は、実際にはオブジェクトをコピーすることです。

2. UDPの特徴

3. データグラム指向

4. UDPバッファ

5. UDP利用時の注意事項

6. UDPベースのアプリケーション層プロトコル

3.TCPプロトコル

1.TCP定義

2. TCPプロトコルセグメントフォーマット

①梱包・開梱方法:

②シェア方法

(1) TCP プロトコルのセグメント形式を詳しく紹介します

(2) メッセージにもカテゴリがあります

(3) 32 ビットのシリアル番号は順番に到着することを保証します—URG

        ①32 ビットのシリアル番号は順番に到着することを保証します。

        ②URG緊急ポインタフラグと緊急ポインタ:

        ③URG アプリケーション シナリオ - サーバー/ホストのステータスを取得するために使用されます

3. 信頼性の問題:

(1) 信頼できないもの: パケット損失、障害、検証失敗。

(2) メッセージが失われたかどうかを確認する方法 (確認応答メカニズム)

4. 確認応答 (ACK) メカニズム

(1) 32ビットシリアル番号/32ビット確認番号

(2) TCP ヘッダーに 32 ビットのシリアル番号と 32 ビットの確認番号の 2 セットのシリアル番号があるのはなぜですか? 頻繁にテストする

5.tcp送受信バッファ

(1) TCP には送信バッファと受信バッファがあります。

(2) 16 ビット ウィンドウ サイズ - フロー制御戦略

(3) tcp テキストの長さはアプリケーション層によって決まります

4. TCP スリーウェイ ハンドシェイク

1 はじめに

2. TCP スリーウェイ ハンドシェイクを行う理由

3. つながりをどう理解するか?

4. なぜ 3 回?

(1) 3ウェイハンドシェイクは成功するのか?

(2) なぜ 1 対 2 の握手ではないのでしょうか?

(3) なぜ 3 回?

5. パケットロスの解決策 - タイムアウト再送信メカニズム

(2) データを繰り返し受信し、シリアル番号を重複排除することができます

(3) 残業時間はどうやって決めるのですか? 

5. 接続管理の仕組み

1. 4回手を振る

2. 4 つの手を振った状態 (ハンドシェイクを含む)

(1) CLOSE_WAIT セミクローズ状態

 (2)TIME_WAIT

        一定期間 TIME _WAIT を設定することの重要性:

        ①MSL:最大伝送時間、往復は2MSL

        ②TIME_WAITの時間はなぜ2MSLなのでしょうか?

        ③TIME_WAIT状態によるバインド失敗の解決方法(ジョブ)

        ④関数setsockoptはクラッシュ時に再起動可能

3. listen の 2 番目のパラメータ - backlog

(1) なぜ並ぶ必要があるのですか?

(2) 行列が長すぎていけないのはなぜですか?


トランスポート層
送信者から受信者へのデータ送信を担当します。

1. ポート番号についてもう一度話します。

1. ポート番号の定義

ポート番号 (Port) は、 ホスト上で通信するさまざまなアプリケーションを識別します
TCP/IP プロトコル では 送信元IP」、「送信元ポート番号」、「宛先IP」、「宛先ポート番号」、「プロトコル番号」の5 つのタプルを 使用して通信を識別します (これを確認できます) netstat -n を介して);

2. ポート番号範囲分割

(1) 合計 2^16 個のポートがあります

0 ~ 1023: HTTP、FTP、SSH などの広く使用されているアプリケーション層プロトコルのウェルノウン ポート番号。ポート番号は固定されており、ポート番号とプロセスは 1 対 1 に対応します。
1024 ~ 65535:オペレーティング システムによって動的に割り当てられるポート番号 8080 などのクライアント プログラムのポート番号は、オペレーティング システムによってこの範囲から割り当てられます。

(2)ウェルノウンポート番号を知る(Well-Know Port Number)

一部のサーバーは非常に一般的に使用されていますが、 使いやすさを考慮して 一般的に使用されるサーバーの一部は 次の固定ポート番号 を使用することに同意します
—— SSH サーバー ポート22 を使用
—— FTP サーバー ポート21 を使用
—— elnet サーバー ポート23 を使用
—— http サーバー ポート80 を使用
- httpsサーバー 443 を使用
このコマンドを実行すると 既知のポート番号が表示されます。
cat /etc/services

ポート番号を使用するプログラムを作成するときは、これらの既知のポート番号を避ける必要があります

3. ポート番号とプロセスはKV関係です

1. プロセスは 複数のポート番号 をバインドできますか? ——はい。 ポート番号: プロセス=K:V
2. ポート番号は複数のプロセスによってバインドできますか? ——いいえ

4.ネット統計

netstat は、ネットワークのステータスを表示するための重要なツールです
構文 : netstat [ オプション ]
機能 : ネットワークステータスの表示
共通オプション :
         n エイリアスの表示を拒否し、表示できるすべての数値が数値に変換されます。
        l Listen (監視) ではサービスのステータスのみをリストします。-ntp は確立されたステータスのみを確認します。
        p は、関連するリンクを確立した PID とプログラム名を表示します。
        t (tcp) はtcp 関連のオプションのみを表示します
        u (udp) udp 関連のオプションのみを表示します
        a (all) はすべてのオプションを表示しますが、デフォルトでは LISTEN 関連は表示されません
通常は netstat -nltp を使用します。

(1) 例 1:  n はエイリアスの表示を拒否し、表示可能な数値はすべて数値に変換されます。

(2) 例 2:  l Listening (モニタリング) でサービスの状態のみを一覧表示する

(3) 例 3:  p は、該当するリンクを確立しているプログラムの名前を表示します。

関連するリンクを確立している PID とプログラム名は、一般ユーザーは表示できません。root 権限のみが表示できます。

5.ピドフ

サーバーのプロセス ID を確認するときに 非常に便利です
構文 : pidof [ プロセス名 ]
機能 :プロセス名 ごとに プロセス IDを表示
UDP プロトコル
UDP プロトコル終了フォーマット

 

2. UDPプロトコル

1. UDPプロトコル終了フォーマット

(1) UDPプロトコルの構造

最初の 8 バイトは UDP ヘッダー、残りはメッセージです

16ビットの送信元ポート番号: 自身のプロセスのポート番号
16ビットの宛先ポート番号: アクセス先のプロセスのポート番号

16 ビット UDP 長: データグラム全体 (UDP ヘッダー + UDP データ) の最大長を示します。これは、UDP をストリーム タイプではなくデータグラム タイプにするためです。
        データグラム: UDP の長さは 16 ビットであるため、メッセージとメッセージの間には明確な境界があります
パケットを UDP 長ごとに 1 つずつ分離し、一度に 1 つずつ受信します。TCP バイト ストリームは、読み取り長がエンコード ヘッダーの長さに達するまで待機する必要があります。
16 ビット UDP チェックサム: チェックサムが間違っている場合は、データに問題があることを意味し、直接破棄され、当面は考慮されません。

(2) ヘッダーはビット セグメントを含む構造です。

(3) ヘッダー追加の本質は、実際にはオブジェクトをコピーすることです。

オブジェクトのメンバー変数を入力し、sizeof (udp_header) のサイズをバイナリにコピーして、それを udp_header (udp_hdr) 型に強制します。

2. UDPの特徴

UDP 送信のプロセスは手紙の送信に似ています。
接続なし:相手側の IP とポート番号がわかっているので、接続を確立せずに直接送信します。
信頼性が低い:  (信頼性が低いとは機能であり、欠点ではなく、中立的な言葉です) 確認メカニズムも再送信メカニズムもありません。ネットワーク障害によりセグメントを相手に送信できない場合、UDP プロトコル層はエラーを返しません。アプリケーション層へのメッセージ; (信頼性が低いとは、送信中に失われた UDP パケットが実際に失われたことを意味します。利点は、信頼性を高めるためにこれ以上の作業を行う必要がないことです --> シンプルなコード、シンプルなメンテナンス、高効率など)
データグラム指向:読み取りおよび書き込みデータの数と数を柔軟に制御できません。
クラシック UDP の使用シナリオ: ライブ ブロードキャスト

3. データグラム指向

データグラム: UDP の長さは 16 ビットであるため、メッセージとメッセージの間には明確な境界があります

アプリケーション層はメッセージの長さを UDP に送信し、UDP はメッセージを分割も結合もせずにそのまま送信します。
例: UDP で 100 バイトのデータを送信するには:
送信側が sendto を 1 回呼び出して 100 バイトを送信した場合、受信側も 100 バイトを受信するために対応する recvfrom を 1 回呼び出す必要があります。ループ内で recvfrom を 10 回呼び出して毎回 10 バイトを受信するのではなく、

4. UDPバッファ

UDP には実際の送信。sendto の呼び出しはカーネルに直接渡され、カーネルは後続の送信アクションのためにデータをネットワーク層プロトコルに渡します。
UDP には受信バッファがありますが、この受信バッファは、受信した UDP メッセージの順序が UDP メッセージの送信順序と一致していることを保証できません (つまり、UDP は信頼性を保証していないため、UDP メッセージの順序が狂っている可能性があります)。バッファがいっぱいの場合、再度到着した UDP データは破棄されます。
UDP にはデータの書き込みと読み取りのための 2 つのパスがあるため、UDP ソケットは読み取りと書き込みの両方が可能であり、この概念は全二重と呼ばれます。

5. UDP利用時の注意事項

UDP プロトコルのヘッダーには最大 16 ビットの長さがあることがわかりました。つまり、UDP で送信できるデータの最大長は 64K (UDP ヘッダーを含む) です
ただし、64K という数字は、今日のインターネット環境では非常に小さい数字です。
送信する必要があるデータが 64K を超える場合は、アプリケーション層で手動でサブパッケージ化し、複数回送信し、受信側で手動で組み立てる必要がありますが、これは不可能です

6. UDPベースのアプリケーション層プロトコル

        NFS: ネットワーク ファイル システム
        TFTP: トリビアル ファイル転送プロトコル
        DHCP: 動的ホスト構成プロトコル
        BOOTP: ブート プロトコル ( ディスクレス デバイスのブート用 )
        DNS: ドメイン名解決プロトコル
もちろん UDPプログラムを自分で 作成する 場合には、カスタム アプリケーション層プロトコルも含まれます。

3.TCPプロトコル_

1.TCP定義

TCP の正式名称は Transmission Control Protocol(伝送制御プロトコル )」で、 その名のとおり データ伝送を詳細に制御する必要があります

2. TCPプロトコルセグメントフォーマット

①梱包・開梱方法:

カプセル化: カプセル化は UDP と同じで、TCP_header オブジェクトを定義し、ヘッダー オブジェクトの各値を入力して、このオブジェクトをメッセージの先頭にコピーします。
アンパック: 最初に最初の 20 バイトを読み取り、 4 桁のヘッダー長を 読み取り、 4 桁のヘッダー長 *4 - 20 =  オプション のサイズ。

②シェア方法

「16ビットの宛先ポート番号」は、上位アプリケーション層への配送を実現し、共有を実現するために使用されます。

(1) TCPプロトコルのセグメント形式を詳しく紹介します

TCP パケットはヘッダーとペイロードで構成されます。TCP ヘッダーは、最初の 2 バイトとオプションで構成されます。ヘッダーは可変長です。最初の 20 バイトが標準長で、オプションは可変長です。

送信元/宛先ポート番号: データがどのプロセスから送信され どのプロセスに送信されるかを示します
32ビット シリアル番号/32ビット確認番号 :シリアル番号はメッセージの番号をマークし、確認番号は確認番号より前のすべてのメッセージの受信をマークし、双方向の全二重確認応答メカニズムを保証します。 詳細については、以下を参照してください。 4.—>(1)
4 ビットTCP ヘッダー長 ( 4 ビット ヘッダー長 ): TCPヘッダーが 32ビットビット (単位は4バイト) で何ビットあるか を示します。この値は 4 ビットで、値の範囲は 0000 ~ 1111 です。 0~15 、単位が 4 バイトであるため、TCPヘッダーの最大長は15 * 4 = 60になります。
;標準の長さは 20 であるため、 4 桁のヘッダーの長さは 少なくとも 20 / 4 バイト = 5=0101 となり、 4 桁のヘッダーの長さの範囲は 0101 ~ 1111、20 ~ 60 バイトになります。オプションのサイズは0~40バイトです
6つのフラグビット
•◆

(2) メッセージにもカテゴリがあります

16 ビット ウィンドウ サイズ:応答の本質は、TCP ヘッダーを含めることです。TCP ヘッダーには、サーバーの受け入れ能力を保存する属性フィールドを含めることができます。これは 16 ビットウィンドウ サイズと呼ばれます 。次の 5 を参照してください。—> (2)
16ビット チェックサム : 送信側のパディング 、CRC チェック 受信側のチェックサムが失敗した場合 データに問題があると考えられます ここでのチェックサムには、 TCP ヘッダーだけでなく TCP データ部分も含まれます。 (16ビットチェックサムは送信時にデータに問題がないことを確認し、問題がある場合は破棄するためのものです。この属性は当面考慮されません)
16 ビット緊急ポインタ : データのどの部分が緊急データであるかを識別します
40 バイトのヘッダー オプション : 一時的に無視されます
ACK: 確認番号が有効かどうか
PSH: 受信側アプリケーションに、 TCP バッファーからデータをすぐに読み取るように指示します。
RST: 相手側が接続の再確立を要求します 。RST フラグ を持つセグメントを リセット セグメントと呼びます。
SYN: 接続を確立する要求 。SYN 識別子を同期セグメントと呼びます。
FIN: ローカルエンドが閉じられること 相手に通知します 。FINフラグを保持するエンドセグメントを呼び出します。
SYN:同期フラグビット。メッセージがリンク確立要求である限り、SYN を 1 に設定する必要があります。これは、リンク要求メッセージ (sync の最初の 3 文字)であることを証明します
。 FIN : このメッセージは、リンクを切断するための要求メッセージ テキスト (終了)
ACK : 確認フラグ、1 に設定すると、メッセージが履歴メッセージの確認であるだけでなく、一般的に最も正式な通信の場合、送信されるデータも伝送できることを意味しますACK は 1

PSH : 受信側アプリケーションに TCP バッファからデータをすぐに読み取るように要求します
説明: ブロック的な方法で read 関数を呼び出してデータを読み取る前に、通知の後に read を呼び出します。これにより、より効率的になります。
説明例: 受信バッファのサイズが 100 バイトであるとします。20 バイトを超えると、上位のアプリケーション層に読み取りを通知します。20 は受信データの最低水準点です。受信バッファ内のデータが 20 バイトを超えると、PSH はサーバー オペレーティング システムにデータがあることを上位層に通知し、読み取ってもらいます。
 

 URG : 緊急ポインタフラグビット。機能: メッセージはシーケンス番号を無視し、上位層によって直接読み取られて処理されます。(このメッセージを緊急ポインタメッセージと呼びます)詳細は3→2→(3)を参照してください。

RST : 相手は接続の再確立を要求します。RSTフラグを保持するセグメントをリセット セグメントと呼びます。               

最後の ACK が失われた場合、クライアントは接続がまだ確立されていることを認識せず、メッセージの送信を続けます。サーバーも ACK を受信しないときにこの問題を認識します。この状況を回避するために、サーバーは次のようにします。 ACK を受信しません。接続がリセットされると、SYN+ACK 応答が再送信され、RST も 1 に設定されます。

(3) 32 ビットのシリアル番号は順番に到着することが保証されます — URG

        ① 32 ビットのシリアル番号は順番に到着することを保証します

メッセージが送信されると、順序どおりに到着しない可能性があります。それは信頼できない種類のものです。
パケットを順番に到着させる必要がありますが、どうすればよいでしょうか? —— 32 ビットのシリアル番号により、順番に到着することが保証されます。これはメッセージのシリアル番号であり、受信バッファは受信後にソートできます。

        ②URG緊急ポインタフラグと緊急ポインタ:

TCP でデータが順番に到着する必要がある場合、つまり、一部のデータの優先順位が高くてもシーケンス番号が後である場合、データを制限して緊急に処理することはできません。

解決策:  URG緊急ポインタ フラグを使用します。URG は1 としてマークされ、優先度の高いメッセージのシリアル番号を無視し、上位層によって直接読み取られて処理されます。(このメッセージを緊急ポインタメッセージと呼びます)

16 ビット緊急ポインタ: 緊急ポインタ メッセージを指すオフセット。緊急ポインタ メッセージには 1 バイトのみを含めることができます

        ③ URGアプリケーション シナリオ - サーバー/ホストのステータスを取得するために使用されます

クライアントがサーバーにデータを送信する際、何らかの理由(メモリ不足など)によりサーバーがメッセージを受信できない、またはメッセージの受信が遅い場合があり、この場合、クライアントはサーバーの状態を知りたいため、 1 と マークされたメッセージ URG 緊急ポインタを送信します 。このとき、サーバーは非常に困難な状況下でも、指定された 1 バイトを優先的に受信し、サーバー内に設定された特定のロジックを通じてステータス コード 20 (仮定) を取得します。そして、URG 緊急ポインタ フラグを使用して、指定されたポインタをマークします 。1バイトがクライアントに返され、クライアントは 20 ステータス コードを受け取り、「メモリ不足」のためにサーバーが正常に動作できないことを知り、スタッフに通知します。

3. 信頼性の問題:

(1) 信頼できないもの:パケット損失、障害、検証失敗。

(2) メッセージが失われたかどうかを確認する方法 (確認応答メカニズム)

回答:応答を受け取った場合は、その応答が紛失していないことを確認しますが、そうでない場合はわかりません。信頼性とは、送信したメッセージが相手から応答される場合は信頼できるものであり、応答されないメッセージは信頼できるとは保証されないことを意味します。
詳しく解説:自分が送ったメッセージが相手に届いたかどうかはどうやって分かるのでしょうか?——相手から返信があれば、自分が送ったメッセージは100%相手に届いたということになります!
遠距離通信中は、常に最新のデータが存在します。したがって、100% 信頼できる合意は存在しません。ただし、ローカルでは 100% 信頼できる可能性があります。
ただし、送信されたメッセージに対応する応答がある限り、送信したメッセージは相手に受信されたと考えられます!! 確認
応答メカニズムにより、相手がデータを受信できることが保証されます。

4.確認応答(ACK)メカニズム

(1) 32ビットシリアル番号/32ビット確認番号

合意を確立します。TCP が通信するとき、送信されるメッセージには TCP ヘッダーが含まれている必要があります。

以下の図について説明します。クライアントがペイロードを送信するときは、TCP ヘッダーを運ぶ必要があり、データはすでに入力されています。ランダムに生成された開始シーケンス番号が 1 で、クライアントからサーバーに送信されるヘッダー全体とメッセージのサイズが 1000 バイトであると仮定すると、シーケンス番号は 1 ~ 1000 個を占め、32 ビットのシーケンス番号は 1 になりますサーバーがデータを受信した後にクライアントに応答するために、サーバーは32ビットの確認番号1001 で応答します。これは、受信側がバイト シーケンス番号[1, 1000] の データを受信し、あなたからのデータを期待していることを意味します。 1001以降のバイトシーケンス番号のデータを送信します。

32 ビット シリアル番号/32ビット確認番号:シリアル番号はメッセージの番号をマークします。確認番号は確認番号より前のすべてのメッセージの受信をマークし、後続のメッセージは次のシーケンス番号から送信されます。双方向フル ダブルワーカー確認応答メカニズム。

例: サーバーは 6 つのメッセージを受信し、32 ビットのシリアル番号はそれぞれ 1、2、3、5、6、7 です。応答する場合、クライアントに返される確認シリアル番号には 4 を入力する必要があります。説明: 確認番号は、特定のシーケンス番号より前のすべてのメッセージが受信されたことをクライアントに伝えるためのものです。ここではメッセージ番号 4 が受信されていないため、4 を入力して、4 より前のすべてのメッセージが受信されたことをクライアントに伝えます。 4が届かなかった場合は4日から再発行となります。

(2) TCP ヘッダーに32 ビットのシリアル番号と 32ビットの確認番号の 2 セットのシリアル番号があるのはなぜですか? 頻繁にテストする

TCP プロトコルは全二重であるため、メッセージを送信しながらメッセージを受信できます。

説明: サーバーがあなたに応答 (確認シーケンス番号を入力) すると同時に、メッセージ (独自のシーケンス番号を含む) を送信したい場合はどうすればよいでしょうか? ——クライアントは「食べましたか?」( 32ビットのシーケンス番号を記入)をサーバーに送信し、サーバーは「食べました」( 32ビットの確認シーケンス番号を記入)をクライアントに応答します。 、同時に「もう食べましたか?」を送信します (独自の32 ビット シリアル番号を入力します)。

クライアントは、シーケンス番号と相手の確認シーケンス番号を用いて左から右への信頼性を確保し、サーバは自身のシーケンス番号と相手の確認シーケンス番号を用いて右から左への信頼性を確保する。これにより、双方向の全二重確認応答メカニズムが保証されます。

(3) 

TCP は データの各バイトに番号を付けます これはシーケンス番号です
ACK に は対応する確認シーケンス番号があり これは送信者にどのデータを 受信した 次回はどこから送信を開始するかを通知することを意味します

5.tcp送受信バッファ

(1) TCP には送信バッファと受信バッファがあります。

IO 関数。実際には、これらはすべてコピー関数です。
書き込み/送信関数を使用してデータをカーネル バッファにコピーした後、tcp は適切なタイミングでデータを送信します。カーネルバッファ内のデータをいつ送信するか、どれだけ送信するか、何か問題が発生した場合はどうするか、効率を向上させるための戦略を追加するかどうかは、OS 内の TCP によって決定されるため、TCP は送信制御プロトコルと呼ばれます!

上図からわかるように、バッファの読み取りと書き込みの 1 つのファイル記述子は相互に影響を与えず、TCP 通信が全二重であることがわかります。

(2) 16ビット ウィンドウ サイズ - フロー制御戦略

クライアントがサーバーにデータ パケットを送信するとき、送信が速すぎてサーバーが受信する時間がなくなったらどうなるでしょうか?
—— サーバーの受け入れ能力をクライアントに知らせる必要があります!
1. どのインジケーターがサーバーの受信能力を示しているか受け入れ能力?——受信バッファの残り容量! 
2. クライアントはどうやって知るの? ? ——送信時には応答がある! 応答の本質は TCP ヘッダーを含むことです。TCP ヘッダーには、16 ビット ウィンドウ サイズと呼ばれるサーバーの受信能力を保存する属性フィールドを含めることができます 4. クライアント——>サーバ、サーバ——>クライアント、両方向とも同じ


概要:双方の送信バッファは、相手の受信バッファの受信容量を知っているという条件に基づいて、それぞれに応じてデータ通信を実行します。継続的に更新されるウィンドウサイズにより、定期的に適切なデータサイズを相手に送信する戦略をフロー制御戦略と呼びます。フロー制御ポリシーは両方の方法で機能します。

5. このフロー制御戦略では、16 ビットのウィンドウ サイズを使用して受信能力の属性フィールドを保存しますが、クライアントは、初めてサーバーにデータを送信するときに、サーバーの受信能力をどのようにして知るのでしょうか?

3 ウェイ ハンドシェイク中は、リンクが確立されるだけでなく、ピアに受信能力を通知することも含まれる情報交換が行われます。

(3) tcp テキストの長さはアプリケーション層によって決まります

tcp ストリーミング サービスなので、テキストの長さを考慮する必要はありません。テキストの長さはアプリケーション層自体によって決定される必要があります。たとえば、私たちが作成したエンコードとデコードは、シリアル化された文字列全体に対して実行されます 9\ r\n100 + 200\r\n 抽出長 

4. TCP スリーウェイ ハンドシェイク

1 はじめに

TCP スリーウェイ ハンドシェイク: SYN、SYN+ACK、ACK。SYN は接続を確立し、SYN+ ACK は接続を確立して接続を確認します (つまり応答)。3 番目の ACK はクライアントの応答です。
3 ウェイ ハンドシェイクで接続が確立されると、メッセージのペイロードはデータを埋めずに空になります。(スリーウェイハンドシェイク中にリンク確立、リンク確立成功後にデータ通信データ送信を行う)

図中の斜線は時間がかかることを示しています

2. TCP スリーウェイ ハンドシェイクを行う理由

——tcp はコネクション指向だからです。接続する必要がある場合に使用してください。udp には絶対に必要ありません。

3. つながりをどう理解するか?

——多数の接続、OS はこれらの接続を管理する必要がありますが、どのように管理すればよいですか? ?——最初に、組織内で説明します。接続構造オブジェクトを作成し、その構造を維持します。接続の維持にはコスト、時間、スペースがかかります。

4. なぜ 3 回?

(1) 3ウェイハンドシェイクは成功するのか?

--不確か。tcp は信頼性を保証しますが、通信時に相手に送信したデータが相手に確実に受信されることを保証します。ただし、接続の確立が成功するという保証はなく、失敗する可能性があります。

(2) なぜ 1 対 2 の握手ではないのでしょうか?

--できません。ハンドシェイクはSYN が 1 つだけ送信され、接続がすぐに確立されることを意味します。これは攻撃 (SYN フラッド) に対して脆弱です。SYN フラッド: クライアントが意図的に大量の SYN を送信すると、サーバーは対応する接続​​構造を維持する必要があるため、サーバーは瞬時に完全に占有され、通常の接続が失敗します。2 回目のハンドシェイク(SYN、SYN+ACK) についても同様です。SYN を複数回送信すると、サーバーは ACK 確認をクライアントに送信しますが、クライアントはそれを直接破棄し、費用をかけずに埋められる大量の構造をサーバーに維持させることができます。

(3) なぜ 3 回?

——理由1:ハンドシェイクの回数が奇数であると、接続が正常に確立された後に失われた最後のメッセージのコストがクライアントに転送される可能性があります。最後の確認は、クライアントがサーバーよりも前に接続を確立していることを確認するためにサーバーによって行われます。クライアントが意図的に大量の SYN を送信した場合、サーバーはそれを受信した後、短い半接続で接続構造を維持し、クライアントに SYN+ACK を返します。クライアントは確認のために ACK を受信して​​サーバーに返す必要があります。クライアントが ACK を受信しない場合、サーバーに ACK を送信することはできません。サーバーが受信しない場合は接続失敗とみなされ、サーバーは ACK を受信しません。短期間の半接続構造をクリアする; クライアントが ACK を受信して​​サーバーに返す場合クライアントも自身で接続構造を維持する必要があり、サーバーはクライアントを水の中に引き込みます。クライアントのリソースも減少しているため、サーバーが SYN フラッドでいっぱいになります。これにより、少なくとも 1 つのクライアントが SYN フラッドでサーバーを転覆させることは困難になります (サーバーの攻撃に対する脆弱性を低コストで軽減するため) が、完全に回避できるわけではなく、多数のクライアントが攻撃した場合は不可能です。同時に。

理由 2 : クライアントとサーバーの両方が一連の IO 操作を実行し、最小限のコストで全二重を検証します。

では、クライアントハーフリンクが機能していないのでしょうか?

5. パケットロスの解決策 -タイムアウト再送信メカニズム

ホスト A がホスト B にデータを送信し た後ネットワークの混雑やその他の理由により、データがホストBに届かない場合があります
ホストA が 特定の時間間隔内に B から確認応答を受信しない 場合 、ホスト A は再送信します

(2) データを繰り返し受信し、シリアル番号を重複排除することができます

ただし ホスト A は Bからの確認応答を 受信しませんでした 。ACK が失われたためかもしれませんそのため、ホストB は大量の重複データを受信します (1 ~ 1000 のデータを 2 つ受信します)。その後、TCP プロトコルはそれらのパケットを識別できます。重複パッケージであり、シリアル番号を使用して重複を破棄し、重複排除の効果を実現します。
では タイムアウト時間はどうやって判断するのでしょうか ?

 

(3) 残業時間はどうやって決めるのですか 

        理想的には、 この時間内に確認応答が返される必要があることを保証するための 最小限の時間を見つけます。
        ただし、この時間の長さは ネットワーク 環境によって 異なります
        タイムアウトの設定が長すぎると、 全体的な再送信効率に影響します
        タイムアウトの設定が短すぎると、 繰り返しパケットが頻繁に送信される可能性があります
どのような環境でも高パフォーマンスの通信を保証するために TCP は 最大タイムアウト時間を動的に計算します
        Linux ( BSD Unix Windows も同様 ) では、 500ms単位で タイムアウトが制御され タイムアウト再送信ごとにタイムアウトが決まります。
        時間は500ms の整数倍です
        再送信後も 応答がない場合は 2*500ms待ってから再送信 してください
        それでも応答がない場合は、 再送信のために4*500 ミリ秒待機するなど、 指数 関数に増加します
        再送信が一定回数に達すると、TCP は ネットワークまたはピア ホストが異常であると判断し接続を強制的に閉じ、サーバーはタイムアウトして再送信します

5. 接続管理の仕組み

1. 4回手を振る

通常の状況では、TCP は 接続を確立するために 3 回ハンドシェイクを実行し 切断するには 4 回手を振る必要があります。
 Accept は 3 ウェイ ハンドシェイクとは何の関係もありません。完了した 3 ウェイ ハンドシェイクを表示するだけです。

4 回振る:一方がもう一方に FIN 切断要求を送信し、もう一方が応答に ACK を返します。(特別な状況では 3 回のウェーブが発生します。クライアントが FIN 切断要求をサーバーに送信し、相手が ACK で応答し、FIN が 1 に設定されているときに切断したいだけです。クライアントは 3 回目の ACK を送信します。これは 3 回です)

2. 4 つの手を振った状態 (ハンドシェイクを含む)

サーバーの状態遷移:
        [CLOSED -> LISTEN] サーバーは listenを呼び出した 後、 LISTEN 状態に入り クライアントの接続を待ちます
        [LISTEN -> SYN_RCVD] 接続要求 ( 同期セグメント ) が監視されると、 接続はカーネル待機キューに入れられ 、 SYN 確認メッセージが クライアントに送信されます
        [SYN_RCVD -> ESTABLISHED] サーバーがクライアントから確認メッセージを受信すると ESTABLISHED状態 になり データの読み取りと書き込みが可能になります。
        [ESTABLISHED -> CLOSE_WAIT] クライアントがアクティブに接続を閉じると ( closeを呼び出す)、サーバーは終了セグメントを受け取りサーバーは確認セグメント ACK を返し、CLOSE_WAIT に入ります。
         [CLOSE_WAIT -> LAST_ACK] CLOSE_WAITを入力すると、サーバーが接続を閉じる準備ができたことを意味します(以前のデータを処理する必要があります)。サーバーが実際に closeを呼び出して接続を閉じるとクライアントにFINが送信されます。このとき、サーバーはLAST_ACK状態に入り最後の ACK 到着を待ちます(このACKはクライアントによるFIN 受信の確認です) 。
        [LAST_ACK -> CLOSED] サーバーはFINの ACK を受信し接続を完全に閉じます
クライアントの状態遷移:
[CLOSED -> SYN_SENT] クライアントは connect を呼び出して 同期セグメントを送信します
[SYN_SENT -> ESTABLISHED] 接続 呼び出しが成功すると ESTABLISHED状態に なり データの読み取りと書き込みが開始されます
[ESTABLISHED -> FIN_WAIT_1]クライアントがアクティブにcloseを呼び出すサーバーに終了セグメントが送信さ
FIN_WAIT_1;
[FIN_WAIT_1 -> FIN_WAIT_2]クライアントはサーバーからの終了セグメントの確認を受信し、 FIN_WAIT_2に入りサーバーの終了セグメントの待機を開始します。
[FIN_WAIT_2 -> TIME_WAIT]クライアントはサーバーから終了セグメントを受信しTIME_WAITに入り、LAST_ACKを送信します
[TIME_WAIT -> CLOSED]クライアントは、 CLOSED状態に入る前に、2MSL (Max Segment Life、メッセージの最大生存時間)の時間待機します

(1) CLOSE_WAIT セミクローズ状態

受け入れるかどうかに関係なく、クライアントが閉じていてもサーバーが閉じていない限り、サーバーは常に CLOSE_WAIT 状態になります (一方が閉じていて、もう一方が閉じていない、つまりハーフクローズ状態)。 :

 (2)TIME_WAIT

接続が維持されている間にサーバーを直接閉じると、サーバーがアクティブに閉じる側となり、アクティブに閉じる側は最終的に TIME_WAIT (4 回の手を振るのが完了) に入り、時間を設定して接続が終了します。この期間が経過すると自動的に閉じます。

        一定期間 TIME _WAIT を設定することの重要性:

① 最後の ACK が可能な限り正常に送信されるようにする:クライアントがこの妥当な時間内にサーバーから再送信 FIN を受信しない場合、サーバーは独自の ACK 応答を受信したと見なされます (この妥当な時間内であれば)。期間 に、クライアントはサーバーから再送 FIN を受信すると、送信した ACK 確認応答が失われたと考え、 ACK を再送する必要があります。(詳しくは下記(2)→②で説明します)

        ①MSL:最大伝送時間、往復は2MSL

TCP プロトコルでは、 接続をアクティブに閉じる側がTIME_WAIT状態になり、CLOSED状態に戻るまで 2 MSL (最大セグメント有効期間) 時間待機する必要がある と規定しています
Ctrl-Cを 使用してサーバーを 終了した ため サーバーは積極的に接続を閉じる側ですが、TIME_WAIT中に同じサーバーポートを再びリッスンすることはできません
MSLは RFC1122 で 2 分と指定されています 各オペレーティング システムの実装は異なりCentos7のデフォルト設定値は60 秒です
mslの値は cat /proc/sys/net/ipv4/tcp_fin_timeout 確認できます
TIME_WAITの 指定時間については、 UNP のセクション2.7 を参照してください

②TIME_WAITの時間は        なぜ2MSLなのでしょうか

MSL は TCP メッセージの最大存続期間であるため、TIME_WAIT が 2MSL 持続する場合、両送信方向の未受信または遅延メッセージ セグメントが確実に消滅することができます (そうでない場合、サーバーはすぐに再起動され、上位の遅延データからメッセージを受信する可能性があります)。プロセスですが、このデータは間違っている可能性があります);
同時に、理論的には、最後のメッセージが確実に到着することも保証されています(最後のACKが失われたと仮定するとサーバーはFIN を再送信します。この時点で、クライアント プロセスはなくなっていますが、 TCP接続はまだ存在しています。、 LAST_ACK は引き続き再送信できます);

        ③TIME_WAIT状態によるバインド失敗の解決方法ジョブ

通常、8080 が切断された後、バインドは失敗し、8081 が変更されます。その理由は、クライアントが積極的に接続を切断した後、 TIME_WAIT 状態に入ります。TIME_WAIT 状態の間、再度使用されない接続がまだ存在します。 , しかし、この接続はまだ保持されています。クライアントの IP とポート、他のプロセスがバインドしたい場合でもバインドできません。これはオペレーティング システムのデフォルトの動作です。
サーバーTCP接続が完全に切断されるまで、再リッスンは許可されませんこれは場合によっては不合理な場合があります。
タオバオ カーニバルを想定すると、サーバーは非常に多くのクライアント接続を処理する必要があります (各接続の有効期間は非常に短いかもしれませんが、毎秒多数のクライアントが要求します)。
このとき、サーバーがクラッシュして積極的に接続を閉じると、大量の TIME_WAIT 接続が生成されます。
リクエストの量が多いため、多数の TIME_WAIT 接続が発生する可能性があり、各接続は通信の 5 つ組 (送信元 IP、送信元ポート、宛先 IP、宛先ポート、プロトコル) を占有します。サーバーの IP、ポート、プロトコルは固定されており、新しいクライアントが要求した IP とポート番号が TIME_WAIT サーバーの IP とポート番号である場合、クライアントは失敗します。
   

        ④関数 setsockoptはクラッシュ時に再起動可能

setsockopt() を使用して、ソケット記述子のオプションSO_REUSEADDR を1 設定します これは、同じポート番号を持つが異なる IP アドレスを持つ複数のソケット記述子の作成が許可されることを意味します。

 

int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
sockfd : 設定するソケット ファイル記述子。level : SOL_SOCKET層を設定します。optname : 設定の名前。通常は SO_REUSEADDR。optval: 値。オプトレン: 長さ

 

3. listen の 2 番目のパラメータ - backlog

リストの 2 番目のパラメーターはバックログと呼ばれ、基礎となる完全に接続されたキューの長さと呼ばれます。アルゴリズムは次のとおりです: n+1 (n はユーザーによって渡された値) は最大で維持できる接続の数を示します受け入れずに。たとえば、2 を渡すと、受け入れずに最大 3 つの接続を維持でき、残りのクライアントが要求した接続はハーフ接続として維持され、フル接続が終了すると、ハーフ接続がフル接続になります。
完全接続維持の意味!

(1) なぜ並ぶ必要があるのですか?

アイドル状態のときにリンクを受け入れて処理することで、サーバーが最下層からリンクを取得できるようにすることができます。プーリング技術に相当し、「接続プール(バッファプール)」を形成します。

(2) 行列が長すぎていけないのはなぜですか?

①長すぎると顧客エクスペリエンスに影響します。
②長すぎるとシステムリソースが占有され、サーバー効率の低下につながる可能性があります。サーバーの効率とサービス能力を向上させるために、長いリンクを維持するためにサーバーにハードウェア リソースを使用させることをお勧めします。

おすすめ

転載: blog.csdn.net/zhang_si_hang/article/details/129036695