[ネットワーク プログラミング · トランスポート層] UDP と TCP に関する古典的な 8 部構成のエッセイ


Linux を学習するためにクラウド サーバーやその他のクラウド製品が必要な学生は、 / --> Tencent Cloud <-- / --> Alibaba Cloud <-- / --> Huawei Cloud <-- / 公式 Web サイトに移動できます。軽量のクラウド サーバーは次のとおりです。年間 112 元の低コストで、新規ユーザーは最初の注文で超低割引を受けることができます。


 目次

1. ポート番号の分割

2. いくつかの指示

1. pidof (プロセス ID の表示に使用)

2. netstat (ネットワークステータスを確認する)

3. UDPプロトコル

1. UDPプロトコル形式

2. UDP プロトコルをカプセル化、解凍、分割する方法

2.1 カプセル化と解凍

使用時間は2.2分

3. UDPプロトコルの特徴

3.1 UDPプロトコルの特徴

3.2 UDPプロトコルバッファ

3.3 UDP プロトコル 16 ビット UDP 長

4. TCPプロトコル(伝送制御プロトコル)

1. TCPプロトコル形式

2. TCPプロトコルの信頼性

2.1 信頼性の低さの反映

2.2 信頼性を確保する方法

3. TCPプロトコルのヘッダー

3.1 カプセル化とアンパッキング(ヘッダー長4桁)

3.2点(16ビット送信元ポート番号、宛先ポート番号)

3.3 TCP プロトコルの 32 ビット シーケンス番号と確認シーケンス番号 (このフィールドは、スライディング ウィンドウとタイムアウト再送重複排除に役立ちます)

3.4 TCP プロトコルの 16 ビット ウィンドウ サイズ (メッセージ送信速度の制御に使用)

3.5 TCP プロトコルの 6 つのフラグ ビット (メッセージ タイプの区別)

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

5. タイムアウト再送メカニズム

6. 接続管理の仕組み

6.1 スリーウェイ ハンドシェイク (接続の確立はクライアントによって開始されます)

6.2 4 回ウェーブする (切断は双方の問題)

7. フロー制御

8. スライディングウィンドウ/高速再送信機構

8.1 スライディングウィンドウの性質

8.2 スライディングウィンドウの役割

8.3 スライディングウィンドウに関するいくつかの質問と回答

9. 輻輳制御

10. 応答の遅れ

11. 応答に便乗する

12. TCP のバイト ストリームの方向と UDP のデータグラムの方向を理解する

13. 粘着袋問題

14. TCPコネクション確立異常の問題

5. UDP/TCPプロトコルの概要

1. TCP の信頼性とパフォーマンス

2. UDP および TCP プロトコルの適用シナリオ

3. listenの第2パラメータについて


1. ポート番号の分割

ポート番号は、値の範囲が 0 ~ 65535 の 16 ビットの符号なし整数です。

0 ~ 1023: 既知のポート番号、HTTP、FTP、SSH、およびその他の広く使用されているアプリケーション層プロトコル。それらのポート番号は固定されています。

従来のポート番号の一部を次に示します。

SSHサーバー、ポート22を使用

FTP サーバー、ポート 21 を使用

Telnet サーバー、ポート 23 を使用

httpサーバー、ポート80を使用

httpsサーバー、443を使用

1024 - 65535: オペレーティング システムによって動的に割り当てられるポート番号。クライアント プログラムのポート番号は、オペレーティング システムによってこの範囲から割り当てられます。 

2. いくつかの指示

1. pidof (プロセス ID の表示に使用)

pidof httpServer | xargs kill -9//xargs用于将标准输入转换为命令行参数

2. netstat (ネットワークステータスを確認する)

n 拒绝显示别名,能显示数字的全部转化成数字
l 仅列出有在 Listen (监听) 的服务状态
p 显示建立相关链接的程序名
t (tcp)仅显示tcp相关选项
u (udp)仅显示udp相关选项
a (all)显示所有选项,默认不显示LISTEN相关

3. UDPプロトコル

1. UDPプロトコル形式

チェックサムが正しくない場合、パケットは破棄されます。

UDP ヘッダーは本質的には構造体オブジェクト、またはビット フィールドを含む構造体です。

struct udphdr {
    uint16_t uh_sport;  /* 源端口号 */
    uint16_t uh_dport;  /* 目的端口号 */
    uint16_t uh_ulen;   /* UDP数据报长度(包括头部+数据) */
    uint16_t uh_sum;    /* 数据校验和 */
};

2. UDP プロトコルをカプセル化、解凍、分割する方法

2.1 カプセル化と解凍

以前にプロトコルをカスタマイズしたとき、ヘッダーとペイロードを区別するために特殊文字を使用しました。

UDP プロトコルは固定ヘッダー長方式に直接従っており、最初の 8 バイトがヘッダーであると見なされます。

使用時間は2.2分

UDPヘッダには16ビットの宛先ポート番号が含まれており、相手のアプリケーション層にはこのポート番号にバインドされたプロセスが存在し、上位層のこのポート番号にバインドされたプロセスはファイルディスクリプタの形で読み込んで、それをアプリケーション層に渡し、特定のプロトコルが処理されます。

3. UDPプロトコルの特徴

3.1 UDPプロトコルの特徴

UDP 送信のプロセスは手紙を送るのと似ており、相手が受け取るかどうかは関係なく、ただ送るだけで完了します。

接続なし:相手側の IP とポート番号を知らずに、接続を確立せずに直接送信します。

信頼性が低い:確認メカニズムも再送信メカニズムもありません。ネットワーク障害によりセグメントを相手に送信できず、パケット損失が発生した場合、UDP プロトコルはアプリケーション層にエラー メッセージを返しません。

データグラム指向:データの読み書きの回数や量を柔軟に制御できないため、sendtoはrecvfromの回数と同じくらい多くなります。アプリケーション層はメッセージの長さを UDP に渡します。UDP は分割も結合もせずにメッセージをそのまま送信します。UDP を使用して 100 バイトのデータを送信します。送信者が sendto を 1 回呼び出して 100 バイトを送信した場合、受信側は次のことを行う必要があります。また、対応するrecvfromを1回呼び出して100バイトを受信することもできますが、ループ内でrecvfromを10回呼び出して毎回10バイトを受信することはできません。

UDP が正常に読み取られると、メッセージが読み取られます。ヘッダーの問題を考慮する必要はなく、ペイロードのシリアル化と逆シリアル化を実行するだけで済みます。

3.2 UDPプロトコルバッファ

UDP には実際の送信バッファがないため、複数の UDP パケットがくっついているという問題は考慮しないでください。sendto の呼び出しはカーネルに直接渡されます (アプリケーション層が 1 つを送信し、トランスポート層が 1 つを送信します)。カーネルはデータをネットワーク層に渡し、プロトコルはその後の送信アクションを実行します。

UDPには受信バッファがあります。ただし、この受信バッファでは、受信した UDP パケットの順序が送信した UDP パケットの順序と一致していることは保証できません。バッファがいっぱいの場合、到着した UDP データは破棄されます。そのため、UDP プロトコルは全二重プロトコルです。

3.3 UDP プロトコル 16 ビット UDP 長

UDP プロトコル ヘッダーには 16 ビットの UDP 長フィールドがあり、これは、UDP メッセージの送信可能な最大長が 2^16 または 64KB (UDP ヘッダーの 8 バイトを含む) であることを意味します。 64KB を超える場合は、申請する必要があります。レイヤーは複数回下請けされ、受信側で手動で組み立てられます。

4. TCPプロトコル(伝送制御プロトコル)

1. TCPプロトコル形式

ヘッダーは構造体オブジェクトです。

struct tcphdr 
{
    uint16_t th_sport;  /* 源端口号 */
    uint16_t th_dport;  /* 目的端口号 */
    uint32_t th_seq;    /* 序列号 */
    uint32_t th_ack;    /* 确认号 */
    uint8_t th_off;     /* 偏移量,指明TCP报文头的长度,单位是4个字节 */
    uint8_t th_flags;   /* 控制标志,如SYN、ACK、FIN等 */
    uint16_t th_win;    /* 接收窗口大小 */
    uint16_t th_sum;    /* 校验和 */
    uint16_t th_urp;    /* 紧急指针 */
};

2. TCPプロトコルの信頼性

2.1 信頼性の低さの反映

ネットワーク伝送距離は非常に長く、路上にある複数のデバイスノードを経由するため、路上でのパケット損失、乱れ、検証エラー、メッセージの重複などの問題が発生する可能性があります。

2.2 信頼性を確保する方法

メッセージの信頼性は、相手から応答があった場合にのみ保証されます。両者が通信する際には最新のデータが必要ですが、例えば図の「12時です」というメッセージは相手からの応答がまだ届いていないため、このメッセージが届いているかどうかは信頼できません。 。

メッセージの応答は単独で送信することも、送信するデータと組み合わせて 1 つのメッセージで送信することもできます。たとえば、上の図では、後続のサーバーが「現在 12 時であるというメッセージを受信しました」と応答します。 「時計、だから13時に行きましょう。」 「遊ぼう!」 これは、応答と送信するデータを1つのメッセージに詰め込むことです。

クライアントがサーバーにメッセージを送信するか、サーバーがクライアントにメッセージを送信するかに関係なく、すべてのメッセージに応答する必要があります。もちろん、純粋な応答メッセージに応答する必要はありません。

3. TCPプロトコルのヘッダー

3.1 カプセル化とアンパッキング(ヘッダー長4桁)

TCP プロトコルの最初の 20 バイトを構造化データに変換し、標準ヘッダー内の 4 ビットのヘッダー長を抽出できます。TCP メッセージの全長 = 4 ビットのヘッダー長 * 4 バイト = [20 バイト (最小 20 バイト)、60 バイト]。ヘッダー フィールドに基づいて計算できる TCP パケットの合計サイズ (標準パケット サイズ) が、メッセージ情報をすべて削除した残りのヘッダーのサイズであり、残りがペイロードになります。

3.2点(16ビット送信元ポート番号、宛先ポート番号)

TCPヘッダーには16ビットの宛先ポート番号が含まれており、サーバー起動時にこのポート番号をバインドすることで、TCPメッセージに対応するアプリケーション層プロセスを見つけることができます。オペレーティング システムがネットワーク プロセスの PCB とポート番号を維持するデータ構造は、ハッシュ テーブルです。

3.3 TCP プロトコルの 32 ビット シーケンス番号と確認シーケンス番号 (このフィールドは、スライディング ウィンドウとタイムアウト再送重複排除に役立ちます)

クライアントは短期間に複数のメッセージを送信する場合がありますが、これらのメッセージがサーバーに到着する順序は不確実であることに注意してください。では、クライアントがサーバーから応答を受信した後、この応答が対応する前に送信したリクエストがどのリクエストに相当するかをどのように区別できるのでしょうか? これは、TCP プロトコルには 32 ビットのシーケンス番号と 32 ビットの確認シーケンス番号があるためです。

シーケンス番号は、TCP プロトコルでデータ パケットを識別するために使用されるフィールドで、送信者によって送信されたデータ パケットのバイト ストリームの最初のバイトのシーケンス番号を表します。シーケンス番号の目的は、データ パケットの順序と整合性を保証することです。TCP プロトコルでは、各データ パケットには一意のシーケンス番号があります。

確認応答番号 (ACK Number) は、受信者がデータ パケットを正常に受信したことを確認するために使用される TCP プロトコルのフィールドで、受信者が受信する予定の次のデータ パケットのシーケンス番号を示します。TCP プロトコルでは、受信側は確認パケット (ACK パケット) を送信して、データ パケットが正常に受信されたことを送信側に伝える必要があります。確認応答パケットの ACK 番号フィールドは、受信側が受信すると予想される次のデータ パケットのシーケンス番号です。

2 セットのシーケンス番号を使用する理由は、TCP プロトコルが全二重であり、クライアントとサーバーの両方が送信者または受信者として機能する可能性があるため、2 セットのシーケンス番号を使用する必要があるためです。

3.4 TCP プロトコルの 16 ビット ウィンドウ サイズ (メッセージ送信速度の制御に使用)

TCP プロトコルがデータを送信するとき、送信者がデータを送信する速度が速すぎると、受信者はそれを読み取る時間がなくなります。メッセージは相手の入力バッファをいっぱいにしてしまいます。相手のバッファがいっぱいであっても、メッセージは送信されます。新しく送信されたメッセージは直接破棄されます。次に、メッセージの送信速度を制御する必要があります。

TCP プロトコルには 16 ビットのウィンドウ サイズがあり、それ自体の入力バッファのサイズを埋めるために使用されます。メッセージが相手に送信されると、相手は入力バッファにどのくらいのスペースが残っているかを知り、データの送信速度を制御できます。

16 ビット ウィンドウ サイズの存在により、通信当事者は受信能力を交換し、フロー制御を実現できます。

3.5 TCP プロトコルの 6 つのフラグ ビット (メッセージ タイプの区別)

サーバーはさまざまな種類のクライアントに直面する可能性があり、接続や応答などを開始するメッセージが存在する可能性があります。さまざまな種類のメッセージを区別するために、TCP ヘッダーにはさまざまな 01 フラグが設定されます。

  1. URG: セット、緊急ポインタフィールドは有効です
  2. ACK: セグメントが受信されたことを確認します
  3. PSH: バッファがいっぱいでない場合でも、受信側に上位層が入力バッファ データをできるだけ早く取得 (プッシュ) できるようにするよう促します。
  4. RST: リセット、異常な接続を強制的に閉じます
  5. SYN: 接続を確立するリクエスト
  6. FIN: 接続を切断します

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

TCP はデータの各バイトに番号を付けます。それがシリアル番号です。各 ACK には、対応する確認シーケンス番号が含まれています。これは、受信したデータと次回どこから送信を開始するかを送信者に伝えることを意味します。

5. タイムアウト再送メカニズム

ネットワーク伝送の信頼性の主な問題はパケット損失の問題ですが、TCP プロトコルの解決策はタイムアウトして再伝送することです。

ホスト A が B にデータを送信し、ネットワークの問題によりパケットが失われた場合、当然、B は A に応答しません。ホスト A は、一定期間確認応答を受信して​​いないことを検出すると、再送信します。

ホスト A がホスト B にメッセージを送信し、ホスト B がメッセージを受信したが応答が失われた場合、ホスト A は一定期間後にメッセージを再送信します。

このように、受信者は 2 つの同一のメッセージを受信し、重複したデータを受信することになるため、これも信頼性の低さを反映しており、受信者は 32 ビットのシーケンス番号に基づいて重複排除を実行する必要があります。

再送時間: データ伝送はその時のネットワーク環境に依存するため、再送時間を固定値に設定することはできず、オペレーティング システムによって動的に再送時間が調整されます。

あらゆる環境で高パフォーマンスの通信を保証するために、TCP はこの最大タイムアウトを動的に計算します。

Linux (BSD Unix および Windows にも同じことが当てはまります) では、タイムアウトは 500 ミリ秒単位で制御され、各タイムアウト再送信のタイムアウトは 500 ミリ秒の整数倍になります。

一度再送信しても応答がない場合は、2*500ms 待ってから再送信してください。

それでも応答がない場合は、再送信まで 4*500 ミリ秒待機するなど、指数関数的に増加します。

TCPは再送回数が一定回数蓄積すると、ネットワークまたは相手ホストに異常があると判断し、強制的にコネクションを切断します。

6. 接続管理の仕組み

3 ウェイ ハンドシェイクは、TCP 接続構造を作成するための基礎です。TCPの接続構造とは、タイムアウト再送、逐次到着、フロー制御、接続状態などを保持し、信頼性を確保するためのデータ構造です。

TCP はコネクション指向であるため、間接的に通信の信頼性が確保されますが、UDP プロトコルはコネクションレスであるため、タイムアウト再送、逐次到着、フロー制御などのデータ構造が保持されず、信頼性が低くなります。 

  1. CLOSED: 初期状態。TCP 接続が確立されていないか、終了していることを示します。
  2. LISTEN: TCP ポートが接続要求を待っていることを示します。
  3. SYN-SENT: TCP 接続要求がリモート ホストに送信され、応答の確認を待っていることを示します。
  4. SYN-RECEIVED: TCP 接続要求がサーバーによって受け入れられ、接続要求を確認する応答が送信されたことを示します。
  5. ESTABLISHED: TCP 接続が正常に確立され、データ送信を開始できることを示します。
  6. FIN-WAIT-1: TCP 接続は閉じられていますが、ローカル エンドポイントは引き続きデータを送信し、リモート エンドポイントからの確認を待つことができることを示します。
  7. CLOSE-WAIT: TCP 接続がピアから終了要求を受信し、ローカル ポートはまだデータを送信できるため、接続が終了したことを示します。
  8. FIN-WAIT-2: TCP 接続を閉じる準備ができているが、リモート エンドポイントにはまだ送信するデータがあり、リモート エンドポイントからの閉じる要求を待っていることを示します。
  9. LAST-ACK: TCP 接続が終了要求を発行し、ローカル ポートとリモート ポートの両方で確認を受信したことを示します。最終確認が送信されて接続の終了が完了します。
  10. TIME-WAIT: TCP 接続が正常に閉じられ、関連するすべてのネットワーク メッセージがクリアされるのを待っていることを示します。通常、CLOSED 状態になるまでに一定の時間がかかります。

6.1 スリーウェイ ハンドシェイク (接続の確立はクライアントによって開始されます)

SYN_SENT は、TCP/IP プロトコルの状態の 1 つで、接続要求 (SYN) を送信し、相手から接続確認 (ACK) が返されるのを待っている TCP クライアントを表します。TCP 3 ウェイ ハンドシェイク接続プロセス中に、クライアントが SYN パケットを送信すると、クライアントの TCP ステータスは SYN_SENT に変わります。この状態では、TCP クライアントは、接続を確立するためにサーバーから返された ACK パケットを受信するまで、サーバーへの SYN パケットの送信を試行し続けます。

SYN_RECV。TCP/IP プロトコルの状態です。TCP 接続の確立中、クライアントから SYN パケットを受信した後、サーバーは応答として ACK および SYN パケットを送信し、クライアントの接続要求を正常に受信したことを示し、クライアントへの接続確認要求を開始します。このとき、サーバーの TCP ステータスは SYN_RECV になります。この状態では、サーバーはクライアントの ACK パケットが TCP スリーウェイ ハンドシェイク接続プロセスを完了するまで待機します。一定時間内にクライアントから ACK パケットを受信しなくても、サーバーは ACK+SYN パケットが失われたと判断し、タイムアウト再送信を開始しますので、心配する必要はありません。

3 ウェイ ハンドシェイクは、クライアントが 3 回目のハンドシェイク中に ACK を送信したときに完了したとみなされ、サーバーはクライアントから ACK 応答を受信したときにのみ 3 ウェイ ハンドシェイクが完了したと見なされます。クライアントとサーバーの間の 3 ウェイ ハンドシェイクの完了時間には差があります。特にクライアントはクライアントの最後の ACK が失われたかどうかわからないため、スリーウェイ ハンドシェイクは必ずしも成功する必要はありませんが、この問題を解決するためのタイムアウト再送信およびその他のメカニズムがあります。

なぜ3回握手が必要なのでしょうか?

TCP はトランスポート層にあり、オペレーティング システムによって管理されるため、TCP 接続の維持には時間とスペースのコストがかかります。

ハンドシェイクの回数が 1 回だけで、クライアントが接続を確立するために SYN を 1 回だけ送信する場合、悪意のある要素がクライアントを利用して狂ったように接続を開始する可能性があります。サーバーには接続を維持するためのコストがかかります。これにより、サーバー上で使用可能な接続の数が増加し、減少します (SYN フラッド)。

握手回数が2回の場合。ワンタイムハンドシェイクと同じで、クライアントがSYNを送信し、サーバーがSYN+ACKを返すと、サーバーは接続が成功したとみなします。また、SYN フラッディングも発生します。

なぜ 3 ウェイ ハンドシェイクを使用するのでしょうか? まず、TCP は全二重通信プロトコルであり、3 ウェイ ハンドシェイクは全二重通信が正常かどうかを確認するための最小限のコストです。次に、SYN フラッディングを防ぐために、クライアントが最後に 3 ウェイ ハンドシェイクで接続を開始したとき、つまりクライアントが最後に ACK を送信したときは、接続が成功したことを意味します。 、クライアント上で接続を確立する必要があります。クライアントが SYN フラッド攻撃を開始したい場合、クライアントも同様の消費を受けることになりますが、スリーウェイ ハンドシェイクにより、単一ホストに対する SYN 攻撃を効果的に回避できます。(ただし、SYN フラッド攻撃の防止は TCP プロトコルでは解決できないことに注意してください。TCP プロトコルの主なタスクはネットワーク通信です。)

ハンドシェイクの回数が 4 回の場合は機能しません。サーバーが最後に ACK 応答を送信した後、ここで接続を確立します。クライアントがこの接続を受信しない方法を見つける限り、接続関係は維持されます。クライアント上で確立されていないため、SYN​​ フラッド攻撃の危険があります。

ハンドシェイクの回数が 3 回以上の奇数の場合は、3 回のハンドシェイクですでに要件を満たしているため、双方の時間を無駄にするためにハンドシェイクの回数を増やす必要はありません。

6.2 4 回ウェーブする (切断は双方の問題)

切断は両当事者の問題であり、両当事者の同意が必要です。

4 つのウェーブ フェーズ中に、クライアントとサーバーの両方がアクティブに切断を開始できます。

一方が切断したい場合、もう一方も切断したい場合があり、その場合、4 波が 3 波になる可能性があります。

積極的に切断する側の最終状態は TIME_WAIT であり、受動的に切断する側は 2 回手を振った後、CLOSE_WAIT 状態に入ります。切断された側で多数の CLOSE_WAIT 状態が表示される場合は、サーバーに過大な負荷がかかり、クローズを実行する時間がないか (サーバーにはまだプッシュされていないデータがまだある)、単にクローズが忘れられているかのどちらかです。

4 つのウェーブが完了した後、積極的に切断した側は一定期間 TIME_WAIT を維持します。

維持する時間: この時間は MSL (MSL: ネットワーク内の TCP セグメントの最長生存時間。この時間が経過すると、セグメントは破棄されます。MSL のデフォルト値は 2 分です) の 2 分です (CentOS7 は 1 分)。 。)

一定期間保持する必要がある理由: 1. 開始者は相手が 4 波のうち最後の ACK 応答を受信したかどうかを確認できず、一定時間待つ必要があるため。 3 番目のウェーブの FIN メッセージ、次にアクティブなパーティ。その後、4 番目のウェーブの ACK 応答メッセージを再送信して、4 番目のウェーブの成功を確認します。2. 双方が切断しても、ネットワークにはまだパケットが残っているため、関連するネットワーク パケットがすべてクリアされるまで待つ必要があります。(そうでない場合、サーバーがすぐに再起動すると、前のプロセスから遅れたデータを受信する可能性がありますが、このデータは間違っている可能性があります)。

サーバーが最初にシャットダウンされ、一定期間内にサーバーが再起動されると、最後にバインドされたポートをバインドできなくなります。そのポートを接続に再利用するには、最後のサーバーのステータスが CLOSED に変わるまで待つ必要があります。 。アクセス数が多いサーバーの場合、サーバーがハングすると、一定期間、多数のポートを再度バインドすることができないため、これは不合理です。setsockopt() を使用すると、同じポート番号で異なる IP アドレスを持つソケット記述子を作成できます。

GETSOCKOPT(2)         
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname,
              void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname,
              const void *optval, socklen_t optlen);
int opt=1;
setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

7. フロー制御

上の章で説明したように、TCP メッセージには 16 ビットのウィンドウ サイズがあります。実際、TCP ヘッダーの 40 バイト オプションにはウィンドウ拡張係数 M も含まれています。実際のウィンドウ サイズはウィンドウの値です。フィールドを M ビット左にシフトします。双方の受信バッファのサイズを交換するために使用されます。3 ウェイ ハンドシェイク中に、両者は TCP メッセージ内の受信バッファ サイズの交換を偶発的に完了しました。

受信バッファがいっぱいの場合、2 つの戦略があります: 1. 受信側の上位層がデータを持ち去ると、受信側は送信側にウィンドウ更新通知を送信します; 2. 送信側は受信側にウィンドウ更新通知を送信します。ウィンドウサイズについては随時終了します。

8. スライディングウィンドウ/高速再送信機構

8.1 スライディングウィンドウの性質

スライディング ウィンドウは本質的に送信バッファの一部であり、送信されたものの応答がなかった送信バッファの部分はスライディング ウィンドウと呼ばれます。

スライディング ウィンドウの移動は、基本的に配列の添字の移動と同じです。

8.2 スライディングウィンドウの役割

  1. フロー制御: TCP スライディング ウィンドウ メカニズムにより、受信側は送信側の送信レートを制御して、受信側が処理能力内でデータを受信して​​処理できるようにすることができます。受信者はスライディング ウィンドウのサイズを調整することで送信者に通知します。また、受信者の処理能力に基づいてスライディング ウィンドウのサイズを動的に調整することもできます。スライディング ウィンドウにより、TCP のデータ送信効率がある程度向上します。
  2. 輻輳制御: TCP スライディング ウィンドウ メカニズムは、ネットワーク内の輻輳の制御に役立ちます。ネットワークの輻輳が発生すると、受信側はスライディング ウィンドウのサイズを縮小してデータ送信速度を低下させることができ、それによってネットワークへのさらなる負荷圧力を回避できます。スライディング ウィンドウのサイズを動的に調整することにより、TCP はネットワークの混雑の程度に応じてデータ送信速度を適応的に制御できます。
  3. 信頼性の高い送信: TCP スライディング ウィンドウ メカニズムにより、信頼性の高いデータ送信が実現します。送信者は受信者が確認したデータを受信した後、次のスライディングウィンドウのデータのみを送信し、受信者も同時に受信したデータを確認します。送信者が確認応答を受信しない場合、または受信者が順序が正しくないデータを受信した場合、送信者はスライディング ウィンドウ メカニズムを通じてデータを選択的に再送信し、データの信頼性の高い送信を保証できます。

8.3 スライディングウィンドウに関するいくつかの質問と回答

スライディング ウィンドウの開始サイズはどのように設定されますか? 未来はどう変わるのか:

スライディング ウィンドウ サイズとは、確認応答を待たずに直接データを送信できる最大サイズを指します。上の図のウィンドウ サイズは 4000 バイト (4 セグメント) です。スライディングウィンドウの大きさは相手の受信能力に関係します。 

スライディングウィンドウは右にスライドする必要がありますか? 左にスライドしますか:

スライディングウィンドウは右にスライドする場合もあれば、動かない(相手の受信バッファがいっぱいでスライディングウィンドウが停止している)場合もあります。ただし、左側のデータは送信され、応答されているため、左側にスライドすることはありません。

引き違い窓のサイズは変わりますか?変更する方法:

スライディングウィンドウは相手の受信能力に応じて動的に変化し、増減する場合があります。

スライディング ウィンドウ内のデータが応答を受信する順序は同じではありません。中央または末尾のデータが最初に ACK された場合、スライディング ウィンドウはどのように処理されるべきですか:

スライディング ウィンドウ ACK の順序が狂ってもスライディング ウィンドウには影響せず、左端の ACK が到着する限り、スライディング ウィンドウは右に移動します。

最も懸念されるパケット損失の問題は次のとおりです。

1. データは失われていないが、ACK が失われた場合。TCP プロトコルには 32 ビットの確認シーケンス番号があるため、これを恐れる必要はありません。たとえば、シーケンス番号 1001 ~ 2000 の ACK が失われた場合でも、クライアントがそのシーケンスの ACK を受信して​​いる限り、数値 2001 ~ 3000 (2000 より大きい) は、以前のメッセージがすべて受信されたことを意味します。次に、ウィンドウを直接 3001 までスライドします。

2. データが失われた場合 (サーバーはデータを受信せず、もちろん ACK もありません)、その後クライアントが同じシーケンス番号を持つ 3 つの ACK パケットを受信すると、高速再送信メカニズムがトリガーされます

後方にスライドしたときに後ろに十分なスペースがない場合はどうすればよいですか:

送信バッファは、オペレーティング システムのカーネルによってリング構造に編成されます。(リング構造の生産者-消費者モデルと同様)

スライディング ウィンドウではピアの受信能力が考慮されるのに、なぜスライディング ウィンドウ内のすべてのデータを一度に送信できないのでしょうか。

 これは、データリンク層の MAC フレーム プロトコルでペイロードが 1500 バイトを超えてはいけないと規定されているため、トランスポート層での 1 回の送信の最大ペイロードは 1460 バイトです。(最大セグメント サイズ MSS) もちろん、トランスポート層での 1 回の送信のペイロード サイズが 1460 バイトを超えても問題ありませんが、IP プロトコルでは過度に大きなメッセージを断片化して組み立てる必要があるため、パケット損失の可能性が高くなります。

9. 輻輳制御

道路を走る車が多すぎるので、渋滞は避けられません。ネットワークも同様で、複数のホストが同時に TCP 通信を行うとネットワークが混雑します。各受信ホストでは突発的に大量のパケットロスが発生し、その際に大量のロスパケットがタイムアウトを越えて無謀に再送されると、ネットワークの状況が悪化することは間違いありません。

輻輳が発生すると、TCP はスロー スタート メカニズムを有効にし、すべてのホストが最初に少量のデータを送信してパスを探索し (同時に送信されるメッセージの数が減り、ネットワークの圧力が大幅に軽減されます)、その後送信速度を上げます。ネットワークの状況を理解した上で料金を設定してください。以下に示すように:

図には、ネットワークのストレージ容量を反映する輻輳ウィンドウ (ネットワークの状態に応じてサイズが変化する)という概念もあります。

スロースタート機構:

1. 送信開始時に、輻輳ウィンドウ サイズを 1 として定義します。

2. ACK 応答を受信するたびに、輻輳ウィンドウは 1 ずつ増加します (2 倍、1 は 2 になり、2 は 4 になり、4 は 8 になります。指数関数的増加。初期段階では、スロースタート パスを実行するために指数関数的増加が使用されます)。パス探索に成功すると、ネットワークに問題がないことを意味し、同時にインデックスが急激に上昇し、通信速度がすぐに最大値に回復します。成長後期に輻輳ウィンドウを 2 倍にしても意味がありません。したがって、後の期間で輻輳ウィンドウを単純に 2 倍にすることはできず、スロー スタートと呼ばれるしきい値を導入する必要があります。輻輳ウィンドウがこのしきい値を超えると、指数関数的に増加するのではなく、直線的に増加します)。

3. 実際に送信されるウィンドウ サイズ = min (輻輳ウィンドウ、ピア ホストによって提供される TCP ヘッダー内の 16 ビット ウィンドウ サイズ)。

3 番目の点の説明:

送信者の送信能力は、次の 3 つの状況によって異なります。

1. 送信者のスライディング ウィンドウ サイズ。

2. ピア ホストによって提供される TCP ヘッダーの 16 ビット ウィンドウ サイズ。(ピア受信バッファ)

3. 現在のネットワークの輻輳ウィンドウ

1. TCP が開始されるとき、スロー スタートしきい値はウィンドウの最大値に等しくなります (図の 24 に等しい)。

2. 各タイムアウトおよび再送信中に、スロー スタートしきい値は元の値の半分になり、輻輳ウィンドウは 1 にリセットされます (図のしきい値は 24 から 12 に減少します)。

10. 応答の遅れ

送信側は相手側の受信バッファにメッセージを送信します。メッセージを受信した後、相手側は受信バッファにまだ 1M あることを知り、すぐに応答して送信側にまだ 1M あることを伝えます。受信バッファを確保して送信すると、次回は1Mの容量に応じてフロー制御を行います。ピアが遅延応答を採用した場合、上位層は受信バッファ内のメッセージの一部を取り除く可能性があり、より大きなスペースに応答して応答の数を減らすことができます (32 ビットの確認シーケンス番号があります)。 TCP では、前のシーケンス番号を持つメッセージが受信されたことを確認できます)。遅延確認応答により、ネットワークのスループットが向上する可能性があります。

もちろん、これはすべてのパケットの応答が遅れるという意味ではありません。

1. 数量制限: N パケットごとに 1 回応答します。

2. 制限時間: 最大遅延時間を超えた場合は 1 回応答します (タイムアウト再送信時間未満である必要があります)。

具体的な数とタイムアウト期間はオペレーティング システムによって異なります。通常、N は 2、タイムアウト期間は 200 ミリ秒です。

11. 応答に便乗する

一方の端がもう一方の端にメッセージを送信します。メッセージの送信を減らすために、もう一方の端は ACK フラグを 1 に設定し、32 ビットの確認シーケンス番号とペイロードを伝送して、反対側の端に送信します。(ペイロードを運ぶ応答は、TCP で一般的な通信方式でもあり、メッセージの送信効率を向上させることができます)

12. TCP のバイト ストリームの方向と UDP のデータグラムの方向を理解する

write を呼び出すアプリケーション層の本質は、データを送信バッファにコピーすることです。データがいっぱいの場合、データは一時停止されます。read を呼び出すアプリケーション層の本質は、受信バッファからデータを読み取ることです。データが存在しない場合、満席の場合は中止とさせていただきます。双方に読み取り/書き込みバッファがあるため、TCP は全二重通信プロトコルです。

TCP プロトコルの場合、アプリケーション層から与えられるデータ内のメッセージの長さは考慮されず、TCP プロトコルにとって、アプリケーション層から与えられるすべてのデータはバイトです。バッファの存在により、TCP プロトコルの読み取りと書き込みが一致する必要はなく、上位層がどれだけのバイトを与え、または要求するか、これらのバイトをどのようにメッセージに結合するかなど、TCP はまったく気にしません。それらをメッセージに結合し、アプリケーションが自分で解決策を考えますたとえば、アプリケーション層は write を複数回呼び出して合計 100 バイトを書き込むことができ、ピアは read を 1 回呼び出して 100 バイトを読み出すことができます。(UDP はデータグラム用です。送信するには一度読み取る必要があります。受信するたびにメッセージである必要があります。このメッセージは後でシリアル化および逆シリアル化できます。この独立したメッセージの送信はデータグラム指向と呼ばれます)

13. 粘着袋問題

上で述べたように、TCP はメッセージ合成を考慮せず、スティッキー問題を独自に解決するためにアプリケーション層を必要とします。

スティッキーな問題を解決する本質は、メッセージ間の境界を明確にすることです。

境界を明確にする方法:

1.固定長読み取り戦略:固定長パケットの場合、毎回固定サイズで読み取られるようにします。たとえば、上記のリクエスト構造は固定サイズであるため、バッファーの先頭から開始して sizeof を押します。 (お願い)順次お読みください

2.パケット ヘッダーの合意パケット長戦略:可変長パケットの場合、パケット ヘッダーの位置にあるパケットの全長のフィールドについて合意できるため、パケットの終了位置がわかります。

3.特殊文字分離戦略:可変長パッケージの場合、パッケージ間で明確な区切り文字を使用することもできます (区切り文字がテキストと競合しない限り、アプリケーション層プロトコルはプログラマ自身によって決定されます)。

14. TCPコネクション確立異常の問題

1. TCP クライアントとサーバーの一方または両方がハングアップします。

電話を切る前に、TCP クライアントとサーバーは接続されていました。一方の通話が終了すると、オペレーティング システムは自動的に 4 回手を振り、通常どおり切断します。(手動で close を呼び出すのと変わりません) 

2. マシンを再起動します

OSもプロセスを送信しました。オペレーティング システムは再起動する前にプロセスを終了するため、この状況はプロセスの通常の終了と変わりません。

3. マシンの電源がオフになっているか、ネットワーク ケーブルが抜かれています。

電源がオフになった側には、メッセージを送信する前に相手側にメッセージを送信する時間がありませんでした。相手側は定期的に問い合わせを開始し、複数回無応答が続くと切断されます。(接続管理メカニズムの場合、そのほとんどはアプリケーション層 (HTTP、HTTPS など) によって管理されます。アプリケーション層の特定のプロトコルには、HTTP の長い接続などの検出メカニズムもあり、接続のステータスも定期的に検出されます。たとえば、QQ は切断後、定期的に TCP スリーウェイ ハンドシェイクを再開始して接続しようとします)

5. UDP/TCPプロトコルの概要

1. TCP の信頼性とパフォーマンス

信頼性:

チェックサム、シーケンス番号(順番に到着)、確認応答、タイムアウト再送、接続管理、フロー制御、輻輳制御

性能を上げる:

スライディングウィンドウ、高速再送信、遅延応答、ピギーバック応答、フロー制御、輻輳制御

2. UDP および TCP プロトコルの適用シナリオ

UDPは、生放送、QQ初期、動画伝送など、高速伝送やリアルタイム性が要求される通信分野で使用されています。また、UDPは放送にも使用できます。

TCP は信頼性の高い送信のために使用され、ファイル転送や重要なステータスの更新などのシナリオで使用されます。

どの契約を最終的に使用するかは、企業のリーダーシップによって異なります。

3. listenの第2パラメータについて

int listen(int sockfd, int backlog);

TCPプロトコルは、上位層に対して完全な接続キューを保持します。キューには、3ウェイハンドシェイクが完了した接続対象のオブジェクトが含まれます。このキューを無視することはできません。その存在は、外食に行くときに並ぶ必要があるようなものです。 . 最後の顧客が去りましたが、キューはまだそこにあります。ユーザーはすぐに接続できるため、TCP の速度が大幅に向上します。もちろん、キューが長すぎることはできません。キューが長すぎるため、待ちますか? 同じTCP の場合は true ですが、このキューの維持にはオーバーヘッドが必要なため、キューが長すぎる必要はありません。この完全な接続キューは、listen の 2 番目のパラメータの影響を受けます。

listen の 2 番目のパラメータは 2 に設定されます。4 回目に接続が確立されると (クライアント 36648)、クライアントは接続が正常に確立されたと考えていることがわかりますが、サーバー側では接続確立のステータスがSYN_RECVです。(クライアントは接続を確立するリクエストを開始します。リクエストを受信すると、サーバーは SYN_RECV 状態になり、クライアントに SYN+ACK 応答を送信し、クライアントが正常に接続を確立できるようにします。ただし、クライアントが 3 番目のリクエストを開始すると、ハンドシェイクでは、クライアントの ACK は無視されます。サーバーは通話時に接続を確立せず、まだ SYN_RECV 状態にあります。これは半接続状態と呼ばれます)。

TCP の最下層では、最大でバックログ + 1 つのフル接続が許可され、後続のすべての接続はハーフ接続になります。(セミ接続ができるだけ早くハンドシェイクを完了しない場合、サーバーによって自動的に閉じられます)

1. セミリンクキュー (SYN_SENT および SYN_RECV ステータスのリクエストを保存するために使用)

2. フル接続キュー (accpetd ​​キュー) (確立された状態にあるリクエストを保存するために使用されますが、アプリケーション層は accept を呼び出しません)

 (注: Wireshark を使用してTCP通信プロセスを分析できます)

おすすめ

転載: blog.csdn.net/gfdxx/article/details/132126000