TCP通信の仕組み1

コネクション型とと呼ばれる仕組みです。

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]を受け取ってコネクションを閉じたことにしています。

以下に、このイメージを示します。(セグメントのデータ部が100byteの場合の例です。)
クライアント セグメントの流れ サーバ
接続要求
SYN ビットをセットして送信
次でこの接続要求に次で応える
ACK+SYN 接続要求を送信
ACKで 接続要求に次で応える
接続状態の確立
データを送る
シーケンス番号:101
受信できた。
サーバの受け取り確認 受信できたことを送る
シーケンスACK番号:201
次のデータを送る
シーケンス番号:201
障害による受信失敗
ACKを待つタイムアウト
同じデータを再送
シーケンス番号:201
受信できた。
サーバの受け取り確認 受信できたことを送る
シーケンスACK番号:301
データの送受信が続き、 以下で接続状態の終了例を示す(以下はクライアントからであるがサーバ側からも可能)
終了すること知らせる
FIN ビットをセットして送信
受信できた。
サーバの受け取り確認 受信できたことを
ACKのビットをセットして知らせる
サーバの受け取り確認 終了すること知らせる
FIN ビットをセットして送る。
受信できたことをACKのビットを
セットして知らせ、FINも送る
接続状態の終了

上記において、通信路の色が接続されてない状態を示し、 通信路の色が接続中を示しています。
この矢印の移動している情報がTCPセグメントのイメージです。
セグメント中のコントロールフラグで、SYNが0でACKのビットが1にセットされる状態が、 コネクション確立状態です。
なお、データを送信するセグメントで、 同時にそれを前の受信の確認応答セグメント([ACK]がセット)としても使います。
このように、その他必要な制御情報をデータ送信セグメントにセットするような兼用的使い方が でき、ビギーバックと呼ばれます。
(単に確認応答のみを送信するよりも効率が良くなります)
 
TCPの接続状態はnetstatコマンドで確認できます。 以下にnetstatコマンドのStateで表されるキーワードの意味を表として示します。
クライアント状態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