Webエンジニアのブログ

「マスタリングTCP/IP 入門編」要約 第6章「TCPとUDP」

マスタリングTCP/IP 入門編 第5版」の第6章の要約。

この章ではトランスポート層のプロトコルであるTCP(Transmission Control Protocol)とUDP(User Datagram Protocol)について説明する。

トランスポート層の役割

トランスポート層とは

TCPは信頼性のある通信を提供し、UDPは同報通信や細かい制御をアプリケーションに任せたほうがよい通信に用いられる。IPヘッダにはどのトランスポートプロトコルにデータを渡すかが番号で示され、またトランスポート層のTCPやUDPでも、ヘッダに次にどのアプリケーションに渡すかを識別するための番号が定義されている。

通信の処理

TCP/IPのアプリケーションプロトコルは、一般にクライアント/サーバーモデルと呼ばれる形式で作られている。サーバーはクライアントからの要求を処理してサービスを提供するような形になる。 サーバーがクライアントからの要求を待つプログラムは、UNIXではデーモン(常時起動されているプロセス)と呼ばれる。例えばHTTPのサーバープログラムはhttpd。sshのサーバーははsshdと呼ばれる。またUNIXでは個々のデーモンを動かすのではなく、その代表としてクライアントからの要求を待つinetd(インターネットデーモン)というスーパーデーモンが使われる。このスーパーデーモンはサービスの要求を受けるとforkして、sshdなどのデーモンに変身する。そしてそれ以降のソリはforkされたデーモンが要求を受け持つ。

TCPとUDPの使い分け

信頼性があるからといってTCPが優れたプロトコルというわけではない。UDPは高速性やリアルタイム性を重視する通信などに利用される。例えば人と人との対話をするIP電話などが例としてあげられる。UDPは音声の再送処理を行わないため、音声が遅れたり、多少のパケットが乱れても一時的に音声が乱れるだけである。マルチキャストやブロードキャストの通信でもUDPが使われている。

ポート番号

トランスポートプロトコルにおけるアドレスはポート番号である。このポート番号はプログラムのアドレスを識別するときに利用される。TCP/IPやUDP/IPでは、「宛先IPアドレス」「送信元IPアドレス」「宛先ポート番号」「送信元ポート番号」「プロトコル番号」の5つの数字の組み合わせで通信を識別する。どれかひとつでも違えば、別の通信だと判断される。

番号の割り当て

HTTPやFTPなど広く使わているアプリケーションプロトコルでは使用するポート番号が決められている。これをウェルノウンポート番号と呼び、0~1023までの番号に割り当てられている。これらの番号を別の用途に使うことは推奨されない。 またウェルノウンポート番号以外にも正式に登録されているポート番号があり、これは1024~49151となっているが、別の用途に使っても大きな問題にはならない。

他にはダイナミックに割り当てる方法がある。サービスを提供する側(サーバー)はポート番号が決まっている必要があるが、サービスを受ける側(クライアントの)のポート番号は必ずしも決まっている必要はない。アプリケーションは自分のポート番号の決定をOSに任せることができ、OSはアプリケーションごとに同じに値にならないようポート番号を割り当てる。つまり送信元ポートは動的な番号になり、サーバー側はその送信元ポートにレスポンスする。

この動的なポート番号の割り当てによって、同じアプリケーションから複数のTCPコネクションを確立した場合でも、通信を識別する5つの番号が同じにならないようにしている。この番号の範囲は49152~65535までの整数が利用される。

ポート番号とプロトコル

異なるトランスポートプロトコルの場合は同じポート番号を使用することができる。例えばTCPとUDPでは同じポート番号を別の目的で使用することが可能になる。

UDP

UDP(User Datagram Protocol)は複雑な制御は提供せず、IPを用いてコネクションレスの通信サービスを提供する。またアプリケーションから送信要求のあったデータをそのままネットワークに流す。

UDPはネットワークが混雑していたとしても送信料を抑制するようなふくそうを回避する制御を行わない。またパケットが失われても再送制御は行わない。これらの制御が必要な場合はUDPを使うアプリケーション側で処理する必要がある。UDPは総パケット数が少ない通信(DNS、SNMP)や、リアルタイム性が必要な通信(動画や音声)に向いている。

TCP

TCP(Transmission Control Protocol)はパケット喪失時の再送制御や順序制御などを行う。またコネクション制御があり、通しない手がいるかどうかを確認してから通信を行うため、無駄な通信を抑制できる。

シーケンス番号と確認応答で信頼性を提供

TCPでは、送信したデータが受信ホストに到達したとき、受信ホストは送信ホストにデータが到達したことを知らせる。これを確認応答(ACK、アック)という。逆にパケットに何らかの損失があった場合は、否定確認応答(NACK、ナック)を行う。もしACKが返ってこなかった場合にはデータが喪失したと判断してもう一度同じデータを送信する。この場合ACKパケット自体が喪失した可能性もあるが、同じようにもう一度同じデータを送信する。

もし確認応答パケットが到着するまでに遅延が生じた場合、同じデータを重複して送信する可能性がある。その場合は受信側で重複したデータを削除する必要がある。この制御はシーケンス番号を使って行われる。シーケンス番号は、送信するデータ1オクテットごとに付けられる連続した番号のこと(スタート値は乱数で決められる)。受信側では受信したデータのシーケンス番号とデータ長を調べ、次に自分が受信すべき番号を確認応答として返送する。

再送タイムアウトの決定

再送せずに確認応答の到着を待つ時間を再送タイムアウト時間という。この時間は、ラウンドトリップ時間(Round Trip Time、往復時間)とその揺らぎ(RTTの揺らぎ、分散)を計測し、そして計測した時間の合計値よりも少し大きな値になる。ただし最初のパケットはRTT時間がわからないので、6秒程度に設定される。

コネクション管理

TCPはデータ通信前にTCPヘッダだけからなるコネクション確立要求のパケット(SYNパケット)を送信して確認応答を待つ。また通信が終了したときにはコネクションの切断処理(FINパケットの送信)を行う。以下ようにコネクションの確立と切断には、最低でも7つ以上のパケットがやり取りされる。これをスリーウェイハンドシェイクと呼ぶ。

  1. Client: SYN(コネクション確立要求)
  2. Server: ACK(SYNに対する確認応答)、SYN(コネクション確立要求)
  3. Client: ACK(SYNに対する確認応答)
  4. (コネクションの確立完了)
  5. Client: FIN(コネクションの切断要求)
  6. Server: ACK(FINに対する確認応答)
  7. Server: FIN(コネクションの切断要求)
  8. Client: ACK(FINに対する確認応答)

TCPはセグメント単位でデータを送信

TCPでは、コネクションの確立時に通信を行うデータ単位を決定する。これを最大セグメント長(Maximum Segment Size、MSS)と呼ぶ。理想的なセグメント長はIPで分割処理されない最大のデータ長になる。このMSSはスリーウェイハンドシェイク時に決められ、お互いのホストはTCPヘッダにMSSオプションを付け、自分のインターフェイスに適したMSSを通知する。両者の値のうち、小さい方の値がMSSとして利用される。

ウィンドウ制御で速度向上

1パケットごとに確認応答を行った場合、RTTが長ければ通信性能が低下してしまう。そこでTCPではウィンドウという概念を取り入れて、送信ホストが確認応答を待たずに複数のセグメントを送信する。このデータの大きさはウィンドウサイズと呼ぶ。受信ホストはウィンドウロープという1オクテットのデータだけを含むセグメントを時々送信して、ウィンドウサイズの最新情報を送信ホストに送る。そうすることで受信側のバッファが満杯になってパケットを喪失することを防ぐことができる。

ふくそう制御

ウィンドウ制御で大量のパケットを連続的に送信することができるが、ネットワークを混雑させてしまう可能性がある。TCPではこれを防ぐため、通信開始時にスロースタートと呼ばれるアルゴリズムに従ってデータの送信量の制御を行う。まず送信側でデータ送信量を調節するためふくそうウィンドウを定義する。そしてスロースタートするときには、ふくそうウィンドウの大きさを1セグメントに設定してデータパケットを送信し、確認応答されるたびに1セグメントずつふくそうウィンドウを大きくしていく。ふくそうウィンドウと相手のウィンドウサイズを比較し、小さいほうの値以下になるようデータを送信する。

第6章 終わり

以上が、TCPとUDPについての説明。TCPに関してはよく整理して説明されていたため、ある程度理解できたと思う。


{ "name": "hareku", "job": "Web Engineer" }