前回までで、同一ネットワーク内の通信(MACアドレス、スイッチング、ARP)の流れを学びました。
今回からは、トランスポート層の仕組みである TCP(Transmission Control Protocol) を学びます。
今回は通信の開始と終了の部分(コネクションの確立・切断)に絞って見ていきます。
なお、シーケンス番号・確認応答番号を使った再送処理やウィンドウサイズ・MSS といった、より詳細な信頼性確保の仕組みについては本シリーズでは扱わず、CCNA 記事群の中で改めて解説します。
トランスポート層は「通信の信頼性」を規定する層です。
また第3回で学んだ通り、トランスポート層で扱われるデータのまとまりは セグメント(Segment) と呼ばれ、インターネット層(IPアドレス)の内側に格納される情報として、送信元/宛先ポート番号などが付与されるのでした。
TCP(Transmission Control Protocol) は、トランスポート層で動作するプロトコルの1つで、次回学ぶUDPと対比して、以下のような特徴を持ちます。
Webサイト閲覧(HTTP/HTTPS)やメール、ファイル転送など、データが確実に届くことが重要な通信 の多くはTCPを使用します。
TCPヘッダには、送信元ポート番号 と 宛先ポート番号 という情報が含まれます。IPアドレスが「どの機器宛てか」を示すのに対し、ポート番号は 「その機器の中の、どのアプリケーション(サービス)宛てか」 を示す情報です。
たとえば1台のサーバが、Webサーバ(HTTP)とメールサーバ(SMTP)を同時に動かしている場合、どちらの通信も同じIPアドレス宛てに届きますが、ポート番号によって「どちらのアプリケーション宛てか」が区別されます。
代表的なポート番号(ウェルノウンポート)には、以下のようなものがあります。

ポート番号は0〜65535の範囲があり、0〜1023 を ウェルノウンポート(Well-Known Port)、1024〜49151 を 登録済みポート(Registered Port)、49152〜65535 を 動的/プライベートポート(Dynamic/Private Port) と呼びます。
PCからサーバへ通信する際、送信元ポート番号には動的ポートの中からランダムに選ばれた番号が使われるのが一般的です。
TCPヘッダには多くのフィールドがありますが、今回のテーマ(コネクションの確立・切断)に関係する主要なものを整理します。

ログインすると、進捗を保存できます。
← ロードマップ に戻る
シーケンス番号・確認応答番号の詳しい使われ方は、次回「TCP②(再送処理)」で扱います。
今回は、コネクションの確立・切断で使われる コントロールビット(フラグ) に注目していきます。

TCPでは実際のデータ送信を始める前に、送信元と宛先の間で 3回のやり取り を行いコネクションを確立します。これを 3ウェイハンドシェイク(3-way handshake) と呼びます。

今回はハンズオンで後ほど確認できるよう、 RT1 から RT2 への通信を例に、流れを見ていきます。
構成は以下の通りです。

TCP を使用するプロトコルを実行すると、まず 3 way handshake が行われます。
今回は Telnet (他の機器にリモートアクセスするプロトコル)を実行すると、3 way handshake 用の TCP segment が生成されます。
TCP segment には今回のコネクションで使用する sP (送信元ポート番号) と dP (宛先ポート番号) の組み合わせ、3 way handshake の始まりを示す SYN = 1, ACK = 0 が記載されています。
sP は動的/プライベートポートの範囲 (49152〜65535) から自動採番されます。
また、データの開始位置を表す seq (sequence number) はランダムなものが割り当てられるため、今回は例として 0、次に受信したい seq を表す ack (acknowledgement number) も 0 が記載されます。

前回学習した通り、TCP header にも IP header や Ethernet header が付与されます。
この流れは前回学習中のため割愛します。


前回学習した通り、RT2 は受信した通信を復号します。
そして、Ethernet header 、IP header の順番に非カプセル化していき、TCP segment を確認します。

すると、SYN = 1, ACK = 0 のため、これが 3way handshake の開始(コネクションの確立要求)を示すものであると理解します。

続いて RT2 はコネクションの確立要求と応答のために SYN = 1, ACK = 1 を示す TCP segment を生成します。
この TCP segment は先ほど受信したものの返送であるため、sP と dP が入れ替えになっています。
また、seq は 0 のままで、ack は seq に 1 を追加した値(今回は 1)を記載します。

RT2 は IP header と Ethernet header を付与し、送信します。


RT1 は受信した通信を復号します。
そして、Ethernet header 、IP header の順番に非カプセル化していき、TCP segment を確認します。

すると、SYN = 1, ACK = 1 のため、これが 3 way handshake の確立要求と応答を示すものであると理解します。

RT1 は応答のために SYN = 0, ACK = 1 を示す TCP segment を生成します。
また、seq は相手から受信した ack の値となるので 1 となり、ack は相手から受信した seq に 1 を足したものなので、こちらも 1 となります。

RT1 は IP header と Ethernet header を付与し、送信します。


RT2 は受信した通信を復号します。
そして、Ethernet header 、IP header の順番に非カプセル化していき、TCP segment を確認します。

すると、SYN = 0, ACK = 1 のため、これが 3way handshake の応答を示すものであると理解します。

これにより、この通信 (sP と dP 及び sIP と dIP の組み合わせ)におけるコネクションの確立が完了となります。
全体概要としては、TCP を用いる場合はこのようにコネクションが1本確立され、その中にお互い送信用のチャネルのようなものがあるイメージとなります。

コネクションが確立できたため、RT1 はここから TELNET のデータに移ります。
まず、TELNET が生成したデータに TCP header を付与します。この際、使用するポート番号の組み合わせは前述の 3 way handshake で確立したコネクションと同じものを使います。
記載されている内容としては SYN = 0, ACK = 1 、seq と ack は 3 way handshake 完了時のもの、そしてデータの大きさを TCP payload があります。

RT1 は IP header と Ethernet header を付与し、送信します。


RT2 は受信した通信を復号します。
そして、Ethernet header 、IP header の順番に非カプセル化していき、TCP segment を確認します。

TCP segment を確認すると dP が tcp_23 であるため、を参照して TELNET にデータを渡し、処理されます。(どのポート番号がどのアプリケーションかはOS 内部で登録/管理されています。)

そして、RT2 は TELNET のデータを確認し、このデータに記載されている処理を実行します。

RT2 は TELNET を受け取ったことを RT1 に通知するため、TCP segment を生成します。
この際、先ほど受信した TCP payload の値を ack に追加します。 ack は元の 1 と 12 (データサイズ) を足した 13 となり、これにより送信元へ届いたデータサイズを通知することができます。seq は相手から受け取った ack の値となるため、1 です。
※戻り通信で TCP segment だけを送るか、データも送るかはアプリケーションの実装により異なります。

RT2 は IP header と Ethernet header を付与し、送信します。


RT1 は受信した通信を復号します。
そして、Ethernet header 、IP header の順番に非カプセル化していき、TCP segment を確認します。

すると、ack が 13 であることから、送信したデータ (TCP payload 12) が正確に届いたことを認識します。

このように、TCP では 3 way handshake によってコネクションを確立し、コネクション上で seq (sequence number) と ack (acknowledgment number) によるデータの到達確認を行うことで、通信の信頼性を実現しています。
もし、ack が確認できなかったり、ack の値が期待したものと異なる場合には再送処理が行われます。
以上が TCP における送信の仕組みです。
最後に、通信が完了しコネクションを切断する際の動作を説明します。接続時は 3 way handshake ということで通信が3回行われましたが、切断時は通信が4回行われます。(お互い送信用のチャネルを切断するイメージです。)
切断時は FIN flag が用いられ、切断要求側 (今回は RT2) が FIN = 1, ACK = 1 とした TCP segment を生成します。(seq と ack は例のため適当な値としています。)

RT2 は IP header と Ethernet header を付与し、送信します。


RT1 は受信した通信を復号します。
そして、Ethernet header 、IP header の順番に非カプセル化していき、TCP segment を確認します。

すると、FIN = 1, ACK = 1 のため、これがコネクションの切断要求であることを理解します。

これを受信した RT1 は FIN = 0, ACK = 1 とした TCP segment を生成します。 また、ack は 受信した seq + 1 なので 211 となります。

RT1 は IP header と Ethernet header を付与し、送信します。


RT2 は受信した通信を復号します。
そして、Ethernet header 、IP header の順番に非カプセル化していき、TCP segment を確認します。

すると、ack が 211 であることから、送信したデータが正確に届いたことを認識します。

続いて、RT1 側も切断要求を行うために TCP segment を生成します。FIN = 1, ACK = 1 となり、srq, ack は先ほどと同じ値が使用されます。

RT1 は IP header と Ethernet header を付与し、送信します。


RT2 は受信した通信を復号します。
そして、Ethernet header 、IP header の順番に非カプセル化していき、TCP segment を確認します。

すると、FIN = 1, ACK = 1 のため、これがコネクションの切断要求であることを理解します。

これを受信した RT2 は FIN = 0, ACK = 1 とした TCP segment を生成します。 また、ack は 受信した seq + 1 なので 32 となります。

RT2 は IP header と Ethernet header を付与し、送信します。


RT1 は受信した通信を復号します。
そして、Ethernet header 、IP header の順番に非カプセル化していき、TCP segment を確認します。

すると、ack が 32 であることから、送信したデータが正確に届いたことを認識します。

これにより、全体概要で記した赤と青のチャネルでどちらも切断処理が行われたため、TCP コネクションの切断が完了します。

なお、今回軽く触れたシーケンス番号・確認応答番号を使った再送処理や、ウィンドウサイズ・MSS(Maximum Segment Size)といったより詳細な信頼性確保の仕組みは、本シリーズ(超基礎編)では扱わず、CCNA 記事群の中で改めて解説します。
次回は TCP とは対照的な、コネクションレス型のシンプルなプロトコルである UDP を学びます。