【OSI 参照モデル レイヤ4 トランスポート層】TCP/UDP とは

本記事は以下の書籍を元に OSI 参照モデルレイヤ4 トランスポート層について説明します。

最もおすすめの書籍

有名な書籍

前者2つよりも難易度が高め

OSI 参照モデルやその他のレイヤの解説については以下の記事をご確認ください。

スポンサーリンク

トランスポート層とは

トランスポート層とは、以下の5つの機能により、送信元から送信先までのデータ転送に対する信頼性を提供する層です。
コネクション
再送制御
順序制御
フロー制御
輻輳制御
また、トランスポート層では、送信先アプリケーションを指定するための「ポート番号」も規定します。※1

※1 TCP/IP ではトランスポート層に相当する部分だが、OSI参照モデルではセッション層に当たる

https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88%E5%B1%A4

上記の機能を提供するトランスポート層の代表的なプロトコルは次の2つです。

  • TCP(Transmission Control Protocol)
  • UDP(User Datagram Protocol)

TCP とは

TCP(Transmission Control Protocol)は、事前にコネクション(専用の論理的な通信路を確保すること)によって、確実に送信先にデータを届けるためのプロトコルです。

TCP は以下の機能を持ちます。

TCP ヘッダのフォーマット

TCP ヘッダのフォーマットは以下のとおりです。

https://www.infraexpert.com/study/tcpip8.html
フィールドの名称ビット数各フィールドの説明
送信元ポート番号16 bit送信元のポート番号
送信先ポート番号16 bit送信先のポート番号
シーケンス番号32 bit次にデータの何バイト目から送信するか、送信先に通知する番号
順序制御に利用
ACK 番号32 bit次にデータの何バイト目から受信したいか、送信元に通知する番号
再送制御(データを受信したことを保証するため)に利用
データオフセット4 bitTCPヘッダの長さを表す
予約6 bit将来の拡張用
コントロールフラグ6 bit各 bit が先頭から順に通信制御上の以下の意味を持ちます。(1の時コントロールフラグが有効)
・URG:「緊急ポインタ」フィールドが有効
・ACK:「ACK 番号」フィールドが有効
・PSH:flush 動作によって送信されたデータ
・RST:コネクションを強制的に終了。異常終了時に利用
・SYN:コネクションの確立の要求
・FIN:コネクションを正常に終了
ウィンドウサイズ16 bit受信側が一度に受信できるデータ量(バッファサイズ)を送信側に通知するために使用
フロー制御(のウィンドウ制御)で利用
チェックサム16 bitTCP ヘッダとデータ部分のエラーチェックを行うために使用
再送制御(のエラーチェック)に利用
緊急ポインタ16 bit緊急データの開始位置を示す
オプション可変長上記以外の制御処理に使用。例えば、MSSを決定するために使用
パディング可変長オプションが 32bit の倍数じゃない場合は Padding(空データ 0)で埋める

UDP とは

UDP(User Datagram Protocol)とは、コネクションレス(コネクションを確立しない)な通信を行うプロトコルです。通信制御を行わないため信頼性が低いが、無駄な通信を行わないため高速に通信可能な特徴を持ちます。

UDP は「ポート番号」の機能しか持ちません。

UDP は通信制御機能を持たないため信頼性が低く、アプリケーションがパケットロスを検知 or 許容する必要があります。

一方で、コネクションを確立や通信制御をしないため、高速に動作します。

UDP ヘッダのフォーマット

UDP ヘッダのフォーマットは以下のとおりです。

https://www.infraexpert.com/study/tcpip12.html
各フィールドビット数各フィールドの説明
送信元ポート番号16 bit送信元のポート番号
送信先ポート番号16 bit送信先のポート番号
セグメントサイズ16 bit「UDP ヘッダ」+「UDP ペイロード」のサイズ
チェックサム16 bit誤り検出に利用
スポンサーリンク

コネクションとは

コネクションとは、アプリケーション間の通信を行うための論理的な経路のことです。コネクションにより、エンドツーエンドで通信制御が行えます。

エンドツーエンドとは、再送制御など高度な処理はなるべくシステムの末端(エンドシステム)で行い、ネットワーク経路上はなるべく単純な処理のみを行うというものです。

例えば、以下のようにエンドツーエンドではエンドシステムでのみ再送制御(エラー確認)を行います。これにより、ネットワーク経路上の負荷を抑えることができたり、複雑な仕組みの実装範囲をエンド側だけに絞ることができます。

また、TCP コネクションはエンドツーエンドで通信可能であれば、ルーターの故障等により IP 層で経路が変化した場合であっても、コネクションは切断されません。

コネクションの確立:3ウェイハンドシェイク

コネクションの確立をするためには、3ウェイハンドシェイクを利用します。

3ウェイハンドシェイクは TCP ヘッダのコントロールフラグを利用して以下の手順で実行します。

  1. 送信がコネクションの確立を要求するために、SYN を送る
  2. 送信が次のコントロールフラグを返す
    1. コネクションの確立の要求に応答するために、ACK を返す
    2. 送信先から送信元へのコネクションも確立するために SYN を送る
  3. 送信が送信先からのコネクションの確立の要求に応答するために ACK を返す

「CLOSE」や「LISTEN」等は TCP の接続状態(後述)を表します。

なお、コネクションの確立後、以下の制御を行います。

コネクションの切断

コネクションを切断するためには以下の手順を踏みます。

  1. どちらかがコネクションの切断を要求するために FIN を送る
  2. FIN を受け取ったことを表す ACK を返す
  3. 逆側のコネクションも切断を要求するために、 FIN を送る
  4. FIN を受け取ったことを表す ACK を返す
http://www5e.biglobe.ne.jp/aji/3min/39.html

なお、FIN を受け取ってすぐにクローズしない理由は、ACK が届かなかった時に ACK を再送する必要があるからです。(クローズすると、ACK の再送先がわからなくなります)

「ESTABLISHED」や「CLOSE」等は TCP の接続状態を表します。

ソケットとは

ソケットとは、「アプリケーション」が「トランスポート層」や「ネットワーク層」と情報をやりとりするためのインターフェイスです。

https://www.ibm.com/docs/ja/i/7.3?topic=programming-how-sockets-work

コネクションの確立コネクションの切断をする場合、OS では以下のようにシステムコールを利用して動作しています。

https://www.ibm.com/docs/ja/i/7.3?topic=programming-how-sockets-work

システムコールについては以下の記事をご覧ください。

ソケットの状態(TCP の接続状態)

ソケットの状態(TCP の接続状態)の状態遷移図については以下のとおりです。

https://qiita.com/mogulla3/items/196124b9fb36578e5c80

ソケットの状態(TCP の接続状態)の詳細は以下のとおりです。

ソケットの状態説明
ESTABLISHEDソケットは確立した接続状態にある
SYN_SENTソケットは接続を確立しようと試みている
SYN_RECV接続要求をネットワークから受信している
FIN_WAIT1ソケットはクローズされており、接続は切断中である
FIN_WAIT2接続はクローズされ、ソケットはリモート側からの切断を待っている
TIME_WAITソケットは、クローズ後にリモートからの切断が再送されるのを待っている
CLOSEDソケットは使用されていない
CLOSE_WAITリモート側は既に切断され、ソケットがクローズされるのを待っている
LAST_ACKリモート側は既に切断され、ソケットもクローズされている。 確認 (ACK) を待っている
LISTENソケットは接続待ち (listen) である
CLOSING両方のソケットが切断されているが、まだ全てのデータが送られていない
UNKNOWNソケットの状態は不明である
https://linuxjm.osdn.jp/html/net-tools/man8/netstat.8.html
スポンサーリンク

再送制御とは

再送制御は、データが破損、喪失した場合に再送することです。

  • データの破損確認は、TCP ヘッダの「チェックサム」フィールドにて行います。
  • データの喪失確認は、TCP ヘッダのコントロールフラグの「ACK」にて行います。

例えば、データが喪失した時は以下のように再送制御を行います。

ちなみに送信側の ACK の待ち時間を RTO(Retransmission TimeOut)といい、1-60 秒です。(初期値は RFC 2988 では 3秒でした。今は RFC 6298 を使ってます)

When the first RTT measurement R is made, the host MUST set

SRTT <- R
RTTVAR <- R/2
RTO <- SRTT + max (G, K*RTTVAR)
where K = 4.

https://datatracker.ietf.org/doc/html/rfc6298

順序制御とは

順序制御は、データが元の順番で再現できるように制御します。

前提知識:MSS

Layer2 でイーサネットを利用して通信する場合、イーサネットⅡフレームのフォーマットとしてデータフィールドが最大 1500 byte までと決まっています。(詳細は以下の記事)

そのため、1回に送れる TCP セグメントのユーザデータサイズ※は、IP ヘッダの 20 bytes と、TCP ヘッダの 20 bytes を除き、1500 - 20 -20 = 1460 bytes となります。

※ MSS ( Maximum Segment Size )と言います。

つまり、1460 bytes より大きいデータを送る場合は、データを分割して複数回に分けて送信する必要があります。

シーケンス番号とは

シーケンス番号は、これから送信するデータの番号です。分割したデータの順序を制御するために利用します。

シーケンス番号を利用してコネクションでデータを送信する方法は以下のとおりです。

  1. コネクションが開始すると、「シーケンス番号」から「MSS」を加算した番号までのデータを送信
  2. 「シーケンス番号」から「MSS」を加算した番号までデータを受け取ったことを示す ACK 番号を返却
  3. 「ACK 番号」と同じ「シーケンス番号」からデータの送信を続ける

これにより、データを元の順序で受信可能となります。

フロー制御とは

フロー制御とは、送信したデータが受信側のバッファを溢れないように制御することです。

送られてきたデータは受信側のバッファに一時的に溜め置きし、シーケンス番号順に入れ替えて処理をします。

このバッファから溢れたデータは破棄されるため、通信の信頼性に影響を与えます。そこでフロー制御により送信するデータ量を制御します。

フロー制御の1つにウィンドウ制御が存在します。

ウィンドウ制御とは

ウィンドウ制御とは、受信側が利用可能なバッファサイズを相手に伝えることで通信を制御する方法です。この利用可能なバッファサイズのことをウィンドウサイズと言います。

ウィンドウサイズは3ウェイハンドシェイクで決定します。

ウィンドウサイズまでデータを送信しても、受信側のバッファに一時的に貯蔵可能なため、受信側の ACK を待つ必要がありません。

上記の方法だと、ウィンドウサイズ分のデータ(2920 bytes)を送信した後、ACK 返答するため、ACK の待ち時間が発生します。これを解決するのがスライディングウィンドウです。

スライディングウィンドウとは

スライディングウィンドウは、データを受信する度に ACK を送信する方法です。

ACK を受け取る度に、利用可能なウィンドウサイズがスライドすることからスライディングウィンドウと呼ばれます。

バッファが埋まった場合

送信者が増え、受信側の処理が追いつかない時は、受信側がウィンドウサイズを調整します。

また、ウィンドウサイズを0にすることで、一時的にデータの送信を禁止することを「ゼロ・ウィンドウ・プローブ」と言います。

http://www5e.biglobe.ne.jp/aji/3min/42.html

輻輳制御とは

輻輳制御とは、ルータの処理速度や回線速度を上回るパケットの送信を制御することです。

ルーターの処理速度や回線速度を上回るパケットはバッファに一時的に保存されますが、いずれバッファから溢れて消えてしまいます。これを輻輳と言います。

輻輳を防ぐために主にスロースタートアルゴリズムを利用します。

スロースタートアルゴリズムとは

スロースタートアルゴリズムとは、一度に送信するセグメントの数を徐々に増やしていくことで、輻輳が発生するしきい値を探る方法です。

以下のように輻輳が発生すると、一度に送信するセグメント数を半分にしながらしきい値を探ります。なお、輻輳が発生しない場合は、最大でウィンドウサイズまでセグメントを送信可能となります。

http://www5e.biglobe.ne.jp/aji/3min/42.html

ポート番号とは

ポート番号とは、プロセス(アプリケーション)を識別するための番号です。

ポート番号により、ホストに届いたセグメントがどのアプリケーション宛か判断することが可能です。

アプリケーションのポート番号は自由に設定できますが、一般的には以下のようにルールが存在します。

ポート番号の種類ポート番号用途利用場所
Well Known Port Number0 ~ 1023インターネットでよく使われるサービスに利用するポートサーバー側
Registered Port Number1024 ~ 49151ソフトウエアベンダーの独自アプリケーションで利用するポートサーバー側
Dynamic Port Number49152 ~ 65535プライベートで自由に利用可能なポートクライアント側

Well Known Port Number のうち、特によく利用するポート番号は以下のとおりです。

ポート番号TCP/UDPアプリケーション
22TCP/UDPSSH
53TCP/UDPDNS
443TCP/UDPHTTPS
587TCPsubmission(SMTP)

ポート番号の一覧は wiki に記載があるのでご覧ください。

TCPやUDPにおけるポート番号の一覧 - Wikipedia

なお、ポートはプロセス単位で割り当てられるため、同じアプリケーションでもプロセスが異なれば異なるポートを持ちます。(例えば、複数のブラウザを立ち上げれば、異なるポートを利用します。)

netstat コマンド

netstat コマンドは、以下のトランスポート層に関連する情報を取得可能なプロトコルです。
トランスポート層のプロトコル
ポート番号
ソケットの状態(TCP 接続状態)
・ローカル側ソケットのアドレスとポート番号
・リモート側ソケットのアドレスとポート番号

netstat コマンドの使い方は以下のとおりです。

netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN     
tcp        0      0 <サーバーのIPアドレス>:22         <クライアントのIPアドレス>:30613        ESTABLISHED
tcp6       0      0 :::111                  :::*                    LISTEN     
tcp6       0      0 :::22                   :::*                    LISTEN  
項目項目の説明
Protoソケットで用いられているプロトコル (tcp, udp, raw のいずれか)
Recv-Qこのソケットに接続されたユーザープログラムに渡されなかったデータのバイト数
Send-Qリモートホストに受け入れられなかったデータのバイト数
Local Addressローカル側ソケットのアドレスとポート番号
Foreign Addressリモート側ソケットのアドレスとポート番号
Stateソケットの状態(TCP 接続状態)
https://linuxjm.osdn.jp/html/net-tools/man8/netstat.8.html

その他のレイヤについて

OSI 参照モデルの4層目のトランスポート層に関する説明は以上となります。

他のレイヤについては以下をご覧ください。

参考資料・おすすめの書籍

最もおすすめの書籍

有名な書籍

前者2つよりも難易度が高め

3 Minutes Networking
ネットワークエンジニアとして
ネットワークエンジニアに必要なネットワーク技術とCisco・Juniper・F5製品の技術解説。NWエンジニアの仕事内容や年収を紹介。ネットワークスペシャリスト、CCNA/CCNP/CCIEの情報発信。