TCP/IPをわかりやすく - 通信プロトコルの基礎知識を図解で学ぼう

現在のインターネットを支える技術であるTCP/IPについて、基礎となるプロトコル群と、TCPの基本機能を丸田一輝さん、 中山悠さんに解説していただきました。

TCP/IPをわかりやすく - 通信プロトコルの基礎知識を図解で学ぼう

今からおよそ50年前、パケット交換方式による世界初のコンピュータネットワークであるARPANETが構築されました。それ以来、TCP/IP(Transmission Control Protocol / Internet Protocol)は通信を実現する基盤技術として使われ続けています。今ではパソコンに限らず、スマートフォンやゲーム機、センサー、最近では自動車など、無線通信機能を持ったさまざまな端末も含めコンピュータネットワークは構成されています。

その中でも「通信の信頼性を確保する」役割を担っているTCPは、その性質上、多くの機能を備えています。加えて、時代とともに進化するアプリケーションの要求に合わせて常に進化を続けています。本稿では、現在のインターネットを支える技術であるTCP/IPについて、基礎となるプロトコル群と、TCPの基本機能について解説します。

プロトコルスタック

コンピュータネットワークは非常に身近な存在である一方で、たくさんの通信プロトコルで支えられる非常に複雑なシステムです。プロトコルは、もともと複数の人間で作業を実行するための取り決めという意味で使われていた言葉ですが、コンピュータネットワークの発展に伴い、ソフトウェア間の通信規約を指すためにも用いられるようになりました。異なるベンダー製品間の通信を実現するために、通信プロトコルは不可欠なものです。

コンピュータは、通信を実現するための一連のプロトコル群を一つのモジュールとして実装しています。このモジュールは、プロトコルスタックと呼ばれたり、プロトコルスイートと呼ばれたりします。プロトコルスタックの実装はOSにより異なりますが、OSI(Open System Interconnection)参照モデルを用いて統一的に表現することができます。

プロトコルを階層化することによって、ソフトウェアの開発者はその階層が担う役割に特化した機能のみ開発すれば良いことになります。これにより、実装の容易化とともに責任の区分を明確にすることができるのです。

OSI参照モデルは7つの階層(レイヤ)で構築され、階層が低いほどハードウェアよりの、階層が高いほどソフトウェアよりの処理を行います。各階層の名称と主な機能は以下のようにまとめられます。

  • 第7層:アプリケーション層
    • それぞれのアプリケーションの中で通信に関係するプロトコルを定める
  • 第6層:プレゼンテーション層
    • アプリケーション固有のデータフォーマットをネットワーク共通のフォーマットに変換
  • 第5層:セッション層
    • アプリケーションレベルで送受信間における通信の接続を管理
  • 第4層:トランスポート層
    • コネクションを確立・切断し、アプリケーションの要求に応じた方法でデータを転送
  • 第3層:ネットワーク層
    • アドレスの管理や経路の選択を行い、宛先までデータを届ける
  • 第2層:データリンク層
    • 物理的に接続された2つの機器間での通信を提供
  • 第1層:物理層
    • 情報ビット列を電気ないしは光の信号に変換し、物理媒体を通して情報伝送

TCP/IPも同様に階層型プロトコルの概念としてモデル化されていますが、OSI参照モデルとはやや異なります。両者の対応関係と、該当するプロトコルの例を以下に示します。

1

OSI参照モデルにおけるセッション層以上は、TCP/IPではアプリケーション層に属しており、ほとんどの機能は個々のアプリケーションによって実装されます。実際にはほとんどのアプリケーションはOSI参照モデルではなく、TCP/IPに準拠しています。

OSI参照モデルは機能別にプロトコル階層をモデル化しているのに対し、TCP/IPは実装や実用性を主眼にしてモデル化されていることから、現在までに広く普及してきた、という背景があります。

TCPとは

TCPの基本スペックは、インターネット技術の標準仕様群であるRFC(Request For Comments)793に規定されています。TCPは「コネクション型」と分類され、送受信を行う機器間で通信の開始と終了を確認します。データ転送時には、送信側はデータを送信し、受信側はそれに対する確認応答であるACK(Acknowledgement)を返すことによって、両端のホスト間でデータが届いたかどうかを確認し合いながら確実にデータ転送を行います。

通常、データの送信単位にはデータ部とヘッダ部があり、ヘッダは各階層ごとにフォーマットが規定されています。TCPでは、両ホストはトランスポート層のヘッダのみを参照し、通信のやりとりを行います。またTCPではこの送信単位のことを「セグメント」と呼びます。

TCPのヘッダには、「セグメントが何番目まで送られたか」を示すシーケンス番号や、「何番目まで受け取りました/次は何番目が欲しい」ということを示す確認応答番号、「受信可能なセグメント量」を示すウィンドウサイズ等のフィールドが用意されています。以下の図の例では、1000bytesごとにデータを送信し、シーケンス番号が更新されていく様子を示しています。

2

TCPは、通信する両者が同時にデータを送受信可能である全二重通信を提供しますが、ネットワークの状況によっては宛先へ到着するセグメントの順序が入れ替わったり、消失してしまったりすることがあります。

この問題を解消するために、TCPはシーケンス番号によるセグメントの順序制御や、消失したセグメントの再送制御、そしてネットワークの混雑(輻輳、ふくそうと言います)をできるだけ回避するような送信セグメント量の制御、といった機能を持っており、エンドツーエンド間における信頼性の高い通信を実現しているのです。

また、同じトランスポート層プロトコルとしてUDP(User Datagram Protocol)があります。UDPは通信の品質よりもリアルタイム性を重視したプロトコルです。TCPとUDPがそれぞれ備える機能を下の表にまとめます。この図からもわかるように、UDPは非常にシンプルである一方、TCPは多くの機能を備えていることがわかります。以降では、TCPの基本機能を解説します。

3

コネクション管理

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

TCPでは通信を開始する前に、通信相手との間でコネクションを確立します。TCPは全二重の通信を提供するプロトコルなので、送受信側の双方からの接続確立要求を行う必要があります。コネクションの確立は下記の手順で行われます。

  1. 送信側から確立要求としてSYN(コネクションの確立要求)フラグの有効化されたTCPパケットを送信
  2. 受信側はこれに対するACKと、同時に受信側からの接続確立要求として同TCPヘッダのSYNフラグを有効化して送信(SYN+ACK)
  3. 送信側が受信側からのSYNに対するACKパケットを送信

このように3回の送信でコネクションの確立が成立するため、3ウェイハンドシェイクと呼ばれます。この流れを以下に示します。

4

コネクションの切断:ハーフクローズ

コネクションの終了は片方ずつ行います。これは、TCPのデータ転送が全二重通信にて行われている場合、一方のコネクションが先にデータ転送を完了したとしても、もう一方のデータ転送が継続している可能性があるためです。

したがって、コネクション切断が完了するまでには4つのパケットがやりとりされることになります。このプロセスをハーフクローズと呼びます。コネクション切断は、FINに対するACKパケットを返送した後に、一定のタイムアウト期間を待って行われます。双方の切断が完了すれば、TCPによるコネクションの終了となります。

  1. 送信側は最初にFIN(コネクション終了要求)を送信
  2. 受信側はACKを送信し、続けてFINを送信
  3. 送信側はFINを受信して最後のACKを送った後、一定時間待ってコネクション終了

この様子を以下に示します。

5

フロー制御・ウィンドウ制御

フロー(流量)制御

受信側の機器は、データを処理するために一時的に記憶する領域として「バッファ」を備えています。これは機器のCPU等の処理速度も含めてスペックに依存します。受信側では、受け取ったデータをいったん受信バッファに溜めて届け先となるアプリケーションに引き渡します。

受信側が受信バッファよりも大きなデータを受信してしまうと、そのデータを取りこぼし、データの消失と見なされてしまい、送信側に無駄な再送をさせてしまうことになります。このことから、ネットワークの輻輳以前にまず通信機器としての許容量を把握し転送量を調整しなければなりません。そこで受信側は送信側に受信可能なデータサイズをACKとともに通知することで、送信側がセグメントの送信量を調整できるようになっているのです。これを「フロー制御」と言います。

ここで、TCPはデータ転送に「ウィンドウ」という概念を取り入れています。送信側は通知されたウィンドウサイズ分のセグメントを一度に送信できるという仕組みになっています。TCPのヘッダにはウィンドウサイズを通知するためのフィールド(rwnd)が定義されており、受信側は、受信可能なバッファ量をこのフィールドに格納してACKを返答します。送受信側のやりとりとしては、以下のイメージです。

6

ウィンドウ制御

TCPの送信側では、一度に転送可能なデータ量を表すパラメータであるウィンドウサイズ(swnd)が定義されており、これを増減させながら、未送信のデータを転送します。このウィンドウ制御には「スライディングウィンドウ」という考え方が用いられています。

下の図を用いて説明します。ウィンドウ内にあるセグメントはACKを待たずに送信することができるので、図中(a)において、4つのセグメント(2、3、4、5)は一度に送信され、ACKの受信を待っている、という状態です。

次に、(b)の状態に移行します。例えば、スロースタートというフェーズでは、2番のセグメントに対するACKを受信すると、ウィンドウは1つ右へスライドすると同時にその大きさが1つ拡張されます。そして送信待ちであった6番と7番のセグメントが送信されます。このようにして、ACKが到着するたびにセグメント数を増加させながら送出していきます。

7

ウィンドウをスライドさせる際に増減させるウィンドウの数(ウィンドウサイズ)は輻輳の状態等によってさまざまなアルゴリズムによって決められます。このウィンドウサイズは輻輳ウィンドウサイズ(cwnd)として定義されており、以降にて説明するさまざまな輻輳制御アルゴリズムによって能動的に決定されます。ただし、受信側の許容量を超えて送ることはできず、通知されるrwnd値がcwndよりも小さい場合には、rwndが優先されることになります。

TCPでは、「フロー制御」、「ウィンドウ制御」、「輻輳制御」というさまざまな方法によってウィンドウサイズを決定します。それらの関係をここで簡単に整理しましょう。

まず、「ウィンドウ制御」が上位概念に相当し、スライディングウィンドウ方式に基づいてデータの転送を行う、というものです。送信ウィンドウサイズswndを決定するための方法が「フロー制御」と「輻輳制御」となります。

フロー制御は受信側から通知される受け入れ可能なウィンドウサイズrwndに基づいて送信ウィンドウサイズswndを決定するものです。輻輳制御は、ネットワークの輻輳をできるだけ抑えつつ、かつ効率よくデータを転送することを目的とし輻輳ウィンドウサイズcwndを決定するものです。 rwndがcwndよりも小さければ、rwndを優先的に採用します。

輻輳制御・再送制御

エンジニアHubに会員登録すると
続きをお読みいただけます(無料)。
登録のメリット
  • すべての過去記事を読める
  • 過去のウェビナー動画を
    視聴できる
  • 企業やエージェントから
    スカウトが届く