TCPとUDPはOSIのレイヤ4(トランスポートプロトコル)であり、よく以下のように説明されていますよね。
- ●TCP
- ・信頼性が高い
・コネクション型プロトコルである
・ウインドウ制御、再送制御、輻輳(ふくそう)制御を行う
- ●UDP
- ・コネクションレス型プロトコル
・信頼性を確保する仕組みがない
・処理が簡単で遅延が少ない
しかし、これらの説明には重要な視点が欠けていると思います。
データを「ストリーム」として扱うTCPと、「データグラム」を処理するUDPという考え方です。
トランスポートプロトコルとは?
まずは、そもそもTCPやUDPなどのトランスポートプログラムがなぜ必要なのかを考えてみましょう。
ふつう、私たちが利用しているPCやサーバーでは、同じコンピュータの上で複数のアプリケーションが動作していますよね。アウトルックでメールを書きながら、ブラウザでホームページを見たりすることができます。
しかし、IPの世界では、1つのコンピュータには1つのIPアドレスしか割り当てられないのが普通ですね(NICが複数ある場合とか、有線LANと無線LANを同時に使っている場合、仮想マシンを動かしている場合などは例外です)。つまり、メールのデータもWebのデータも、IPの世界では同じアドレスを使って送受信されるので、区別がつかないのです。
また、IPの世界には「順序」という概念がありません。ネットワークに複数の経路がある場合などに、IPパケットが送信した時とは異なる順序で到着する可能性があります。たとえば、大きなデータを複数のIPパケットに分割して転送したときに、データの前と後ろが入れ替わってしまうと、多くのアプリケーションが正常に動作しなくなってしまうでしょう。
したがって、OutlookやInternet ExplolerなどのアプリケーションとIPの世界の間で、データの交通整理をする仕組みが必要であり、それがトランスポートプロトコルの役割です。
具体的には、ポート番号によってアプリケーションを識別したり、チェックサムという仕組みでデータが壊れていないか確認したり、シーケンス番号によってパケットの順序を揃えたり(TCPのみ)する訳ですね(このあたりの技術的な説明は他の文献などに譲ります)。
TCPは「荷造りまでしてくれる宅配便」
では次に、なぜTCPとUDPという2種類のトランスポートプロトコルが必要なのか?ということですが、実は、もともとTCPとIPは1つのプロトコルとして考案されたものであり、後からレイヤ4部分(TCP)とレイヤ3部分(IP)に分割されたという経緯があります。ですので、まずはTCPとIPを一体のものと考えて、どのような働きをしているか整理してみましょう。
たとえば、Outlookで10通のメールを作成し、送信ボタンを押したとします。すると、OutlookからTCP/IPの処理プログラムへメール10通分のデータが渡されます。
このときTCP/IPは、どこからどこまでが1通目のメールで、どこからが2通目か、といったことはわかりませんし、知る必要もありません。なぜなら、TCP/IPの仕事は全てのデータをメールサーバへ確実に送り届けることであり、メールのヘッダを読んで仕分けたりするのはメールサーバの仕事だからです。
ただし、メール10通分のデータを送るためには複数のIPパケットに分割して送信する必要があるでしょう。なぜなら、Ethernetの最大フレームサイズが1518バイトなので、大きなデータは分割しないと入らないからです。
このような処理はTCP/IPが責任を持って実行します。逆に言うと、アプリケーションは自分が渡したデータを何個のパケットに分割すればよいか、などといったことを気にせずに送りたいデータをTCP/IPへ任せてしまうことができます。
TCP/IPは、分割したパケットの順序がネットワークの途中で入れ替わっても、それを検知して元の順序に戻してから、アプリケーションにデータを渡します。また、途中でデータが壊れたり損失した場合には、送信元に再送を要求して完全なデータを復元させます。アプリケーションを開発する人は、TCP/IPを利用することで、コンピュータ間の通信に必要なプログラムを自分で作る必要がなくなります。
このようにTCP/IPは、異なるコンピュータ上で動作するアプリケーションの間で、データを確実に送受信するための運送屋さんのような働きをしています。
このとき重要なことは、TCP/IPが、データを切れ目のない流れ(ストリーム)として扱っている、ということです。TCP/IPを身近なことに例えて言うなら、クロネコヤマトの「荷造りサービス」みたいなものです。
「この部屋にある荷物を全部、××市××番地へ送ってください」とお願いすると、宅急便の人が荷造りして目的地まで送り、荷解きまでしてくれます。依頼人は、どの荷物をどのダンボール箱へ入れるか、ダンボール箱が何個必要か、などを気にする必要がなく、送りたい荷物を部屋に置いておけばよいのです。
これが、「データをストリームとして扱う」ということです。
UDPは「荷造りしない普通の宅配便」
一方のUDPが作られたのは、TCP/IPが考案されてから15年も後の1988年ごろのことです。初期のインターネットではメールやファイル転送などのデータ通信がほとんどであり、TCP/IPの仕組みは理にかなっていましたが、'80年代後半になると「音声」や「映像」などのリアルタイム通信の可能性が検討されるようになりました。
リアルタイム通信においては、パケットを決められた「間隔」で正確かつ定期的に転送することが最も重要ですが、データ通信に最適化して開発されたTCPにはパケットの間隔を制御するような仕組みがなく、逆に再送処理など余計なことをしてしまいます。正直言って「じゃまな役立たず」になってしまいました。
ここで、音声通信に適したトランスポートプロトコルや、映像通信に適したトランスポートプロトコルを作るという方法もあり得たのですが、インターネットの普及とともに様々なニーズが生まれ、他にもTCPでは適さない通信がいろいろと出てくるであろうと考えると、何十種類ものトランスポートプロトコルが必要になってしまいそうです。
そこで、賢明な(無責任な?)インターネット創始者たちは、「何もしない」トランスポートプロトコルであるUDPを作ったのです。
UDPはポート番号によるアプリケーションの識別とチェックサムによるデータ正常性確認という最低限のこと意外は、何もしません。言い換えると、TCPがデータを「ストリーム」の状態でアプリケーションから受け取るのに対して、UDPは「データグラム」(データの塊)を受け取る、という発想の違いがあります。
つまり、アプリケーションの責任でデータの「荷造り」までしてもらい、UDPはデータグラムを目的のコンピュータへ転送するだけです。
先の例で言えば、TCPが「荷造りサービス付の宅急便」だったのに対してUDPは「普通の宅急便」です。荷物をダンボールに詰めるところまではお客さん(アプリケーション)の仕事であり、運送屋さんはダンボールを指定された住所へ届けるだけです。
さまざまなニーズに対応するため何十種類ものトランスポートプロトコルを作るのではなく、「何もしないプロトコル」であるUDPを作り、アプリケーション側で必要な機能を自由に開発させたほうが良いという発想ですね。そして、現在の音声通信や映像通信では、UDPの上で動作するRTP(Real-time Transport Protocol)が(その名のとおり)リアルタイム通信に適したトランスポートプロトコルの役割を果たしています。
他にもUDPは、DNSなど少量で単発的な通信や、RIP・OSPFなどルーティングプロトコルでブロードキャスト・マルチキャスト通信する場合など、コネクション型のTCPでは適さない通信において広く活用されていますね。