TCP/IP プロトコルの三回ハンドシェイク(Three Way Handshake)#
三回ハンドシェイクは、クライアントとサーバー間の TCP 接続を確立するために使用され、接続が信頼性があり、同期されていることを保証します。
-
最初のハンドシェイク:SYN
- クライアントはサーバーに SYN(Synchronize)メッセージを送信し、接続の確立を要求します。
- クライアントは
SYN-SENT
状態に入ります。サーバーの応答を待ちます。
クライアント - SYN ---> サーバー
-
二回目のハンドシェイク:SYN-ACK
- サーバーはクライアントの SYN メッセージを受け取った後、SYN-ACK(Synchronize Acknowledge)メッセージで応答し、接続を受け入れ、同意することを示します。同時に、クライアントに SYN を送信し、逆接続を要求します。
- サーバーは
SYN-RECEIVED
状態に入ります。
クライアント <--- SYN-ACK - サーバー
-
三回目のハンドシェイク:ACK
- クライアントはサーバーの SYN-ACK メッセージを受け取った後、接続が確立されたことを示す ACK メッセージを送信します。
- クライアントは ESTABLISHED 状態に入り、サーバーは ACK を受け取った後、
ESTABLISHED
状態に入ります。
クライアント - ACK ---> サーバー
三回ハンドシェイクの目的#
双方がデータを正しく送受信できることを確認し、双方のシーケンス番号を同期させることです。
TCP が三回ハンドシェイクを必要とする理由の説明#
三回ハンドシェイクは、双方が送信と受信の能力を持っていることを確認するためです(双方が相手に送信と受信の能力があることを確認する必要があります)。
- 最初のハンドシェイク:クライアントがサーバーに、自分がデータを送信できることを知らせます。
- 二回目のハンドシェイク:サーバーがクライアントに、自分がデータを送受信できることを知らせます。
- 三回目のハンドシェイク:クライアントがサーバーに、自分がデータを受信できることを知らせます。
TCP/IP プロトコルの四回ハンドシェイク(Four Way Handshake)#
四回ハンドシェイクは、クライアントとサーバーの接続を切断するために使用されます。TCP は全二重プロトコルであるため、接続を切断する際には双方がそれぞれ送信と受信のチャネルを閉じる必要があるため、四回ハンドシェイクが必要です。
-
最初のハンドシェイク:FIN
- クライアントは FIN(Finish)メッセージを送信し、データを送信しないことを示しますが、データを受信することはできます。
- クライアントは FIN-WAIT-1 状態に入ります。
クライアント - FIN ---> サーバー
-
二回目のハンドシェイク:ACK
- サーバーはクライアントの FIN メッセージを受け取った後、ACK メッセージを送信し、FIN メッセージを受け取ったことを確認しますが、サーバーはまだ送信するデータがある可能性があります。
- サーバーは CLOSE-WAIT 状態に入り、クライアントは FIN-WAIT-2 状態に入ります。
クライアント <--- ACK - サーバー
-
三回目のハンドシェイク:FIN
- サーバーはデータの送信を完了した後、クライアントに FIN メッセージを送信し、データ転送が終了したことを示し、接続を閉じる準備をします。
- サーバーは LAST-ACK 状態に入ります。
クライアント <--- FIN - サーバー
-
四回目のハンドシェイク:ACK
- クライアントはサーバーの FIN メッセージを受け取った後、接続を閉じることを確認する ACK メッセージを送信します。
- クライアントは TIME-WAIT 状態に入り、一定の時間(通常は 2 * MSL、最大パケット生存時間)を待った後、正式に接続を閉じ、CLOSED 状態に入ります。サーバーは ACK を受け取った後、すぐに CLOSED 状態に入ります。
クライアント - ACK ---> サーバー
TCP 混雑制御アルゴリズムの概要#
- スロースタート:接続が確立された後、送信ウィンドウのサイズを初期化し、各 ACK の到着に伴い、ウィンドウサイズが指数関数的に増加し、混雑閾値に達するまで続きます。
- 混雑回避:ウィンドウサイズが閾値に達した後、送信側は毎回 MSS を 1 つだけ増加させます。
- 高速再送:タイムアウトを待たずに、受信側が連続して 3 つの重複 ACK を送信した場合、送信側は即座に該当するセグメントを再送します。
- 高速回復:高速再送段階に入った後、送信側はウィンドウを半分に減少させます。
MTU と MSS の概要#
MTU(Maximum Transmission Unit):最大伝送単位で、ネットワーク層が一度に伝送できる最大データパケットサイズを示します。イーサネットでは通常 1500 バイトです。
MSS(Maximum Segment Size):最大セグメントサイズで、TCP 層が送信できる単一データセグメントの最大バイト数を示し、通常は MTU から TCP/IP ヘッダーサイズを引いたものです。
TCP 粘包問題#
クライアントがサーバーに複数のデータパケットを送信する際、サーバーの下層 TCP 受信バッファにデータが粘りついています。
TCP の下層通信はバイトストリームを対象とした接続指向のプロトコルであり、TCP は送信データの正確性と順序性を保証します。バイトストリームはバイト単位で処理されます。
TCP バッファのサイズが 10 バイトの場合、4 バイトのデータ("aaaa")を送信すると、バッファには 6 バイトの空きが残ります。再度 7 バイトのデータ("bbbbbbc")を送信すると、クライアントが最初に受信するデータは "aaaabbbbbb"
となり、残りの 1 バイトのデータは送信されず、次回の送信を待ちます。
TCP 粘包が発生する原因#
複数の小さなデータパケットが転送中に粘りつき、受信側がこれらのパケットの境界を区別できず、受信したデータが一緒に結合されることになります。
- (送信が速すぎる)クライアントの送信頻度がサーバーの受信頻度を大幅に上回る場合。
- (送信が少なすぎる)TCP の下層の安全性と効率性のメカニズムにより、特に少ないバイト数の小パケットの送信頻度が高くなることは許可されず、TCP は一定のサイズに達するまでデータを蓄積してから一緒に送信します。(Nagle)
- (バッファ残留)送信側のバッファに前回未送信のデータが残っているか、受信側のバッファに未取得のデータがある場合。
TCP 粘包処理の方法#
主にアプリケーション層で定義された送受信パケット形式の方法を使用し、一般的にパケット分割処理と呼ばれます。
TLV プロトコルの使用#
TLV(Type Length Value)プロトコル。
+---------+---------+---------+
| type | length | value |
+---------+---------+---------+
パッケージ送信データ、アンパッケージ受信データ。
区切り文字の使用#
メッセージ間に特殊文字を追加します。
固定長メッセージの設定#
メッセージの長さを規定し、受信側がその長さに基づいて分割します。
TCP が全二重を実現する方法#
- 独立した送信および受信バッファ、通信の両方の側に送信バッファと受信バッファがあり、データを送信する際に受信することができ、逆も同様です。
- 独立したシーケンス番号と確認メカニズム、TCP は送信するデータストリームを複数のメッセージセグメントに分割し、各メッセージセグメントのバイトにはユニークなシーケンス番号が付与され、送信されたデータパケットが全体のデータストリーム内での位置を確保します。受信側はシーケンス番号に基づいてデータの正しい順序を判断し、パケットの損失があるかどうかを確認できます。
- フロー制御、TCP はスライディングウィンドウメカニズムを使用して送信速度を調整し、受信側のバッファがオーバーフローしないようにします(データに圧倒されないようにします)。
- 混雑制御、送信側の送信速度を調整することでネットワークの過負荷を防ぎます。