TCP(Transmission Control Protocol)は、
通信先のプログラムをポート番号で
識別して通信するトランスポート層のプロトコルです。
UDPと違って内部では、確実で効率よくデータを届けるための制御が行われています。
(これは、データを確実に届ける場合でよく使われる ハンドシェイクと呼ばれる手法です。)
そのため次のように、UDPと比べると複雑な構造になっています。
このまとまったデータをセグメントと呼びます
コントロールフラグ内には[URG],[ACK],[PSH],[RST],[SYN],[FIN]のビットがあります。
TCPは、下記で示すように、まず論理的な接続の確立を行います。
つまり、相手が応答して正しく送れることを確認してからでないと、通信しません。
そのためコネクション型と言われます 。
アニメーションで示すように、接続が確立するまで3回のセグメントが行き来し、
3ウェイハンドシェイクと呼ばれます。
接続要求先では、[SYN]ビットをセットして送くります。受け取った方でも[SYN]を返します。
これでシーケンス番号とACK番号の同期(Synchronize)を取ります。
返ってきた[SYN]に対して[ACK]を返すと、接続が確立します。
(なお以下で、TCPによる送受信の情報の単位を、セグメント(segment)と呼んで使っています。)
送ったセグメントに対して応答セグメントをチェックすることで、
確実にデータを伝達したかを確かめられるカラクリがあります。
それは、返ってくるセグメント内の『ACK番号』が、
『次に送ってほしいシーケンス番号』になっている規則で動作します。
(『ACK番号』=『次に送ってほしいシーケンス番号』=
『送信側のシーケンス番号』+『データの送信バイト数』
の関係があります。)
これによって、どこまで相手が受け取っているかを知ることができます。
(なお接続時や、閉じる時などのデータはありませんが、
『データの送信バイト数』は、1byteとして例外的に『送信側のシーケンス番号』+1の設定になります。)
接続をクローズする場合にどちらかが一方的に終了すると、 データを正しく届けられないことがありえます。 よって、双方から[FIN]を送りあって両方で[ACK]を受け取ってコネクションを閉じたことにしています。
クライアント | セグメントの流れ | サーバ |
接続要求 SYN ビットをセットして送信 |
次でこの接続要求に次で応える | |
ACK+SYN 接続要求を送信 |
||
ACKで 接続要求に次で応える |
接続状態の確立 | |
データを送る シーケンス番号:101 |
受信できた。 | |
サーバの受け取り確認 | 受信できたことを送る シーケンスACK番号:201 |
|
次のデータを送る シーケンス番号:201 |
障害による受信失敗 | |
ACKを待つタイムアウト | ||
同じデータを再送 シーケンス番号:201 |
受信できた。 | |
サーバの受け取り確認 | 受信できたことを送る シーケンスACK番号:301 |
|
データの送受信が続き、 以下で接続状態の終了例を示す(以下はクライアントからであるがサーバ側からも可能) | ||
終了すること知らせる FIN ビットをセットして送信 |
受信できた。 | |
サーバの受け取り確認 | 受信できたことを ACKのビットをセットして知らせる |
|
サーバの受け取り確認 | 終了すること知らせる FIN ビットをセットして送る。 |
|
受信できたことをACKのビットを セットして知らせ、FINも送る |
接続状態の終了 |
クライアント状態 | State | 補足説明 | サーバー状態 | State |
---|---|---|---|---|
表示なし | CLOSEED | 接続していない | 待機状態 | LISTENING |
SYN_SENT | 接続要求中 | SYN_REC | ||
データ送受信可能 | ESTABLISHED | コネクション確立中 | データ送受信可能 | ESTABLISHED |
FINセグメント送出からACKを受け取るまで | FINE_WAIT1 | 切断中1 | FINセグメント受け取りから | CLOSE_WAIT |
ACKを受け取ってからFINセグメントが受信まで | FINE_WAIT2 | 切断中2 | CLOSE_WAIT | |
FINセグメントが受信からACK送出まで | TIME_WAIT | 切断中3 | FINセグメント送出からACKを受け取るまで | LAST_ACK |