第5章

トランスポート層プロトコル

更新日:06/01/18 17:45:08


 インターネットでトランスポート層のプロトコルといえば,TCP(Transmission Control Protocol),またはUDP( User Datagram Protocol)です.これらは,いずれもアプリケーションの規定しに従って,IP層以下の下位層のサービスを受けながら,相互に離れた場所にあるホストのプロセス間でのデータ伝送を行うプロトコルです.
 これらのうち,TCPは,送受信ホストのプロセス間に信頼性のあるコネクションを形成します.コネクションを形成するといっても,IPによる論理的コネクションですから,こういうタイプのそれをバーチャルコネクションと言います.TCPは送受信ホスト間にコネクションを確立した上で一連のデータがIP層やアプリケーション層でフラグメントされていようとも一つのものとして時間的に連続的に処理します.それゆえこういうタイプの処理をストリーム型といいます.
 これに対し,UDPはデータをアプリケーション間に送受信するだけのコネクションレス通信で,信頼性はアプリケーションに委ねます.それだけ能率がよいのですが,TCPに比べて信頼性では劣ります.そして,送受信ホスト間で送受されるデータはそれだけが一つのものとして処理されますから,こういうタイプの処理をデータグラム型といいます.Voice over IPや動画映像のような多少信頼に欠けても時間的な流れが重要な通信ではUDPが用いられます.(音声や映像は多少の欠落があっても,人間の目や耳はそれを補正してくれます.)


1. ポート番号

2. UDP(User Datagram Protocol)

3. TCPセグメントの構造

4. TCPの送受信

5. 輻輳制御


第1節 ポート番号

 ポート番号とは,インターネットアプリケーションに付けられた番号のことです.トランスポート層はTCPでもUDPでも発信元ポート宛先ポート二つのアプリケーションのエンド・エンドでデータリンクを形成します.このためしばしばエンド・エンドコネクション(End to End Connection)といいます.その宛先エンドにはマルチタスクOSのプロセスが対応します.そのプロセス種別をインターネットサービスアプリケーションとして16ビットの数値で標準化して表します.だから,理論的にはポート番号は65536存在し得ますが,RFC1700では,「Well Known Port」(標準ポート番号)として,インターネットでよく使われるデファクトスタンダードなインターネットサービスアプリケーション1024個に番号をふって他の使用を禁じています.たとえばポート番号23なら「TELNET」20・21なら「FTP」25なら「SMTP」(Eメール)79なら「FINGER」,80なら「HTTP」などのように,1024個のポート番号についてすでに規格化されています.したがって,個々に開発されたプロセスについては,これ以外の番号を使わなくてはなりませんが,RFC1700にはWell Known Port以外にも準標準的なプロセスについて指示がありますので,実際的にはそれも参照しなくてはなりません.
 このようにTCPやUDPは,ポートとポート(プロセス=アプリケーション)間にコネクションを張って,この間で通信を行うのです.こういうコネクションをバーチャルコネクション(virtual connection)ともいいます.
 TCP層は,IPの助けをかりて,送受信ホスト間でのアプリケーションの実行を助けるために存在します.


  図1.1 TCP/UDPインターフェース 


第2節 UDP(User Datagram Protocol)

 UDPは,コネクションレス型のプロトコルです.下の図のようにUDPデータグラムは単純で,送信元ポートからのデータを,宛先ポートに向かって無手順で転送するだけの機能しか持ちません.つまり,UDPは,発信元ポートと宛先ポートという二つのヴァーチャルコネクション間の無手順通信であるとみなすことができます.それゆえUDPは信頼性のない通信と呼ばれ,現在では特別な目的以外にはあまり使われていません.しかし,TCPのように処理が複雑ではないので能率的であるという利点を有します.そこで,Voice over IPのような音声通信や動画像も含むマルチメディア通信,DNSのデータ互換など,情報の正確さもさりながら時間的な連続性や瞬時性が重要な通信に特定して使われます.
 TCPもUDPもそれより上位のアプリケーションをサービスしていますので,TCPを使うか,UDPを使うかはアプリケーションが決めることです.


図2.1 UDPデータグラム 

UDP発信元ポート番号:16ビットフィールドで,UDPの発信元ホストで実行するアプリケーションのプロセスに関わる番号を入れます.この番号については注意が必要です.この発信元ポート番号には,標準ポート番号以外の任意の番号を入れます.これは,もし標準ポート番号を使ってしまうと,たまたま受信側で複数の同じアプリケーションを処理しているとするとそれを返すときに同じ番号のため混信してしまいます.これを避けるためには発信元のポート番号が異なっていなくてはならないのです.
UDP宛先ポート番号:同様に16ビットのフィールド.宛先ホストのアプリケーションに関わるプロセス種別を表わす標準ポート番号を記入します.たとえばブラウザでホームページをダウンロードするような場合には80(0000000001010000)という数値を入れ込みます.
LENGTH:16ビットフィールドで,ヘッダー部及びデータ部を含む全UDPデータグラムのバイト数.
CHECKSUM:UDPデータグラムのヘッダ部とデータ内にあるIPデータグラムの発信元/宛先IPアドレスを含むデータの誤り訂正用チェックサム.16ビットフィールド.→誤り訂正符号については第7章参照
データ:32ビットの整数倍のデータが入ります.このデータの先頭部にはIPデータグラムのヘッダー部も入っています.
32ビットの整数倍にデータがならないときには,パディングといって0を埋め込んで調整します.

第3節TCPセグメントの構造

 TCPセグメントの構成図を示します.


 図3.1 TCPセグメントフォーマット 

TCP送信元ポート番号:

 送信元コンピュータのプロセスに関わる番号を入れます.この送信元ポート番号には,標準ポート番号以外の任意の番号を入れます.この意味は,UDPで説明しました.16ビットのフィールドが割り当てられます.

TCP宛先ポート番号:

 クライアントが,サーバーのどのポート番号に接続するかを決めるための16ビットのフィールドです.

SEQ(Sequencial Number):送信用シーケンス番号

 32ビットのフィールドです.送信元が送る全データのうち,このデータが何番目のセグメントであるかを表します.(宛先ホストは,この番号に送信元が送ってきたデータの和に1を加えた数値をACKフィールドに入れ込んで返すことで,送信元はこのセグメントが無事相手に届いたことを確認します.) 初期値は時間を引数としたランダム値で与え,一つのセッション中これによってセグメント番号を連続して使います.
 SEQ番号の計算方法は次のとおりです.先に自分が送信したSEQ番号に,「前回送信したセグメントのペイロードのデータ量D(Byte単位)」を加えた数値とします.ただし,コネクションの確立・開放時やコネクションのリセット時のように,データを含まないセグメントパケットの場合にはD=0であるものの1を加えておきます.

ACK(Acknowledgment Number):応答確認番号

 32ビットのフィールドでできています.ここに入れた数値は,自分が次ぎに受信するときの送信先が使うであろう送信用シーケンス番号になります.これによって,パケットの流れや再送確認などが行われます.ACKを受信した送信元ホストは,それと自分の送信用シーケンス番号SEQとが一致していることから,先のセグメントが無事受信されたことを確認します.これが一致しない場合や一定時間経ってもACKが帰ってこなければ,先のセグメントが誤配信されたとして再送します.
 Ack番号の計算方法は次のとおりです.今受信した送信元のSEQ番号に「いま受信したセグメントのペイロードのデータ量(Byte単位)」を加えた数値とします.ただし,コネクションの確立・開放時やコネクションのリセット時のように,データを含まないセグメントパケットの場合にはD=0であるものの1を加えておきます.

HLEN(Header Length):ヘッダ長

 TCPヘッダの長さを32ビット(4オクテット)を単位として,4ビットの数値で示します.オプションフィールドが無ければ5(0101)です.
 このフィールドは4ビットなので15までの数値が入れられます.それゆえTCPヘッダとしては最大15×32=60オクテットまで拡張できますので,オプションフィールドとしては60−20=40オクテットまで使用可能ということになります.

Reserved:リザーブ

 6ビット構成で,将来の拡張性のために確保されているフィールドです.現在は未使用のため000000が入ります.

FLAG:コードビット

 6ビットのフィールドです.その細部を下の図に示します.
URG
は,ここに1が入りますと,Urgent Pointerが有効であることを示し、緊急処理を要求します.
ACK
は,ACKフィールドの有効性を示します.ここに1が入っているときにはACKを使っているのでそれを考慮することを要求しています.
PSH
(プッシュフラッグ)に1があれば,データをアプリケーション層へフラッシュする(送り出す)ことを要求します.Voice over IPのような対話的なアプリケーションで,宛先ホストにすぐに情報が転送されるよう要求する場合に設定されます.
RST
リセットフラッグで,ここに1が入ると,それはセグメントにエラーがあったのでコネクションを解除する「異常終了」のサインです.
SYN
はここに1を入れることでコネクションの確立要求を示します.これでSEQフィールドが有効であることも示します.
FIN
は,終了を示し,最後のセグメントであることを示し,コネクションの開放を要求します.


 図3.2 フラッグコードビット 

WINDOW:ウインドウ

 16ビットのフィールド長を持ちます.複数のセグメント(その一つ一つをウインドウという)を送るたびに確認しあっていては能率が低下します.そこで,何個か一括してセグメントを送り,そのグループについて確認しあうことにすればスピードが上がります.この一括するウィンドウの枚数がスライディングウインドウのウインドウサイズで,このフィールドにはこの数が入ります.
 16ビットなので,65,535迄しかウィンドウは取れないことになりますが,近年のブロードバンドネットワークではもっと多くのウィンドウを使うことでネットワークの高速性能にマッチした通信が要求されますので,その拡張についてはオプションフィールドでこの欠点を補います.

Ckecksum:チェックサム

 ペイロード内の全データとセグメントヘッダの誤り訂正のためのチェックサムです.16ビットのフィールドを有します.送信ホストは自分が送るセグメントパケット全体のチェックサムを計算してここに入れ込み,受信側ではそれを確認して正しければACKを返して受信し,違っていればACKを返さないことで誤りを伝えることになります.→誤り訂正符号については第2章参照

Urgent Pointer:緊急ポインター

 16ビットフィールド.緊急に処理すべきデータの位置を示します.

OPTION:オプション

 HLENで設定された32ビットの整数倍で0〜40オクテットまで拡張可能なフィールドです.フロー制御(ウィンドウ制御)や輻輳制御など,高速ネットワークの出現に伴うさまざまなインターネット新技術が開発・格納されるフィールドになっています.

Payload:

アプリケーションが必要とするデータがこの中にTCPデータとして入ります.

 第4節 TCPの送受信

4.1 TCP送受信の手順

 無手順のUDPに対して, TCPには信頼性を確立するために以下のような手順が含まれています.なお,TCPで使われるパケットは特に違いを強調するためにセグメントという用語を使いますので気をつけましょう.ちなみにIPパケットはデータグラム,EtherNetのようなデータリンク層に出てくるパケットはデータフレームと言います.混乱しないようにしましょう.

1.応答確認

2.再送

3.コネクション管理

4.ウィンドウ制御

5.チェックサム

6.フロー制御

 これらの用語のうち1,2,4の意味をまず下の図で簡単に説明します.


4.2 コネクションの確立

@Node1は,まずIP層の助けを借りてNode2とのコネクションの確立を要求します.この場合,セグメントではペイロード中にデータを含まない,シーケンス番号の同期化を図るためにFLAGフィールドのSYNフィールドに1を入れ,SEQフィールドに初期値を入れます.下図では,Syn=10としました.
Aこれに応えて,Node2はコネクション確立応答を返しコネクションを形成するか,確立を拒否する場合にはコネクション確立拒否(Rst=1)として拒否します.ここでは,確立要求に応諾したとして話をつづけます.
BNode2では確立応答をするために,ACKフィールドに1を入れ,ペイロードににデータを含まないセグメントを返します.そのためにSYNフィールドに1を入れて,SEQフィールドにこれも初期値なのでランダムな数値(ここではSeq=100)を入れます.Ackは@の受信セグメントがSeq=10だったので,これに1を加えた数値Ack=11とします.
Cこのセグメントを受信したNode1は,相手からの確立応諾の確認のために,再度セグメントを返します.すなわち,Seq=11,Ack=101を入れます.

 以上でコネクションの確立が終了しました.このように合計3回のやり取りによってコネクション確立手順を取りますが,これを三方向シェイクハンド(Three Way Handshake)と言います.


 図4.2.1 コネクション確立手順 

4.3 セッション

 下の図のように,コネクションの確立に成功したら,
@ Node2は,要求されたデータ量Dオクテット(ここでは10オクテット)を入れ込んだセグメントを送ります.その際,Node2はシーケンス番号として,先のセグメントのシーケンス番号(Seq=100)に先のデータ量D(ここでは0)に1を加えた数値Seq=101をSEQフィールドに記入し,また自分が送信した先のセグメントのAck=11にそのとき受信したデータ量Dオクテット(ここでは0)に1を加えた数値Ack=12を入れて送出します.
A これを受信したNode1は,D=5オクテットのデータを送信します.そのとき,先に自分が送信したSEQ番号に,「前回送信したペイロードのデータ量D」に1を加えた数値Seq=12,それに今受信した送信元のSEQ番号101に「いま受信したペイロードのデータ量D」を加えた数値Ack=111を記入しておきます.
B Node2は,要求されたデータ量Dオクテット(ここでは20オクテット)を入れ込んだセグメントを送ります.その際,Node2はシーケンス番号として,先のセグメントのシーケンス番号(Seq=101)に先のデータ量D(ここでは10)を加えた数値Seq=111をSEQフィールドに記入し,また自分が送信した先のセグメントのAck=12にそのとき受信したデータ量Dオクテット(ここでは5)を加えた数値Ack=17を入れて送出します.
C これを受信したNode1は,D=3オクテットのデータを送信します.そのとき,先に自分が送信したSEQ番号Seq=12に,「前回送信したペイロードのデータ量D」5を加えた数値Seq=17,それに今受信した送信元のSEQ番号111に「いま受信したペイロードのデータ量D」20を加えた数値Ack=131を記入しておきます.

これらのセッションを必要な回数だけ行うことでセッションが進行していきます.各セッションにおいて,SEQとACKの数値を確認し合うことでそれ以前のセグメントが正しく受信されたことを確認していますので,このような応答を「累積確認応答(Cumulative Acknowledgement)」と言います.
 


 図4.3.1 正常な通信の場合 

  このようにセグメントを一つ送り,先方からのACKを確認してまた一つ送っていると,ACKを確認する作業ばかりが多くかかって通信速度が遅くなります.特にLAN内のように高速の回線では実に不経済です.特に光ファイバのように耐雑音性に優れたネットワークが多用されるようになるとますます不経済が際立ってきます.
 それを避けるためにTCPにはウィンドウの制御機能が込められています.受信側ノードのホストは,そのTCPセグメントフォーマット中のWINDOWの中に一度に送るべきセグメント数を記入して,その数だけ一度に送信することを要求します.受信ホストはそれらの複数のセグメントが無事に到着した場合にはACKを返します.こうして,能率を向上する仕組みがTCPプロトコルには入っています.
 下の図はそのウィンドウが3の場合を図示します.近年の超高速ネットワークではウィンドウの数を桁違いに多くして大量のデータが送られるように規定されています.WINDOWフィールドは16ビットですから要求できるウィンドウの数は最大でも65,535セグメントまでですが,これをオプションフィールドで拡張する機能まで規定しています.


 図4.4.2 Window制御 

4.4 コネクション開放

 送受信ホスト間で通信が完了したら最後に「コネクションの開放」を行います.その手順は下の図のように,大変ていねいなセッションによって行われます.
@ 一方のノードのホスト(ここではNode2)がコネクション開放の宣言をします.そのためにFLAGフィールドのFinフィールドにFin=1を記入します.もちろんペイロード内のデータDは0です.
A これを受信したNode1は,自分もコネクションを終了できる状態であれば下図のようにD=0のACKを返します.(ただし,もしNode1に未だ送るべきデータがある場合には無視して送り続け,それに対してNode2はD=0のセグメントをAckをつけて応答し続けます.ただし,Node2が二度とFinフラグを返すことはしません.)
B Node1が,自分もコネクションを終了したい場合には,D=0でかつAと同一のSeqとAckを入れ,Fin=1を入れたセグメントを返送します.
C Node2は,D=0のセグメントを,通常通りにAck,Seq番号を入れて返答します.
これでセッションは無事に終了です.


 図5.4.1 コネクションの開放 


 

第5節 輻輳制御

 
 Node1がセグメントパケットを送信したが,何らかの原因でNode2側に届かない場合が考えられます.この原因は,インターネットの途中のルータが輻輳(Congestion)を生じ,最悪の場合IPデータグラムパケットを廃棄していると想像されます.こんな時には,いくら待っていてもNode2はACKを返してはきません.一定時間待ってもACKが返送されてこない場合には,Node1は再度セグメントを再送します.その結果,ACKが返されてきた場合には,以後は上の正常時のように全二重通信が行われます.
  下の図はその様子を描いています.図のように,パケット@,A,Bは順調に送信され,正しく受信されましたので,Node2は@,A,Bに関するACKを順次返信していましたが,Cにパケットエラーが発生しました.スライディングウィンドウで全二重通信をしているNode1はそのことに気づきませんので,そのままD,E,Fのパケットを送りつづけます.さいわいこれらは無事にNode2に到着しましたが,累積確認を使命とするNode2は返すべきACKとしてAck3を返しつづけます.このACKが3つ帰ってきたところでNode1はパケットCにエラーの発生したことを認めます.このような重複ACK確認応答(Duplicate Acknowledgement)と言います.
 このように,Ack3が連続して3回帰ってくるまで誤りを認識しないのには意味があります.それは,パケットCが一定時間待ってもACKが返送されてこない理由として,このパケットが何らかの理由で迂回路を経由していて単純に伝送時間がかかっているという場合があります.したがってすぐに対応するよりも少し冗長な時間を見ておいた方が効率がよいからです.
 


 図5.5.1 TCPの流れ 

 上の図では,D,E,Fのパケットは無事に着いていたのに,再度Cのパケットに戻って再送信しているように描かれています.これでは折角の成果が無駄になります.そこで誤ったパケットCだけを再送して,D,E,Fは受信ホストのバッファーに格納しておいて,全パケットの送信が終えたところでアプリケーションに渡すようなシステムも使われています.
 しかし,いずれにしてもTCPはストリーム型通信ですから,全パケットが受信されてはじめてアプリケーションに転送されるという仕組みは同じです.TCPが信頼性を担保しているのはこの仕組みによるのです.

 5.2 致命的なパケットエラーの場合

 上の例は,パケットエラーはあったがたまたまのエラーであった場合です.そうではなくてネットワークが遮断したり,Node2のサーバーがクラッシュして動作不能に陥ったような致命的な事故の場合を考えてみましょう.インターネットでは常に存在するケースです.
 このような場合には,Node2は何時まで待っていてもACKが帰ってくることはありません.そのような場合には,下の図のように最後のACKが届いた時刻から時計を動かして一定の時間以上経過した時点で送信を中止します.この時間をタイムアウト時間(Retransmission Time Out)RTOといいます.


 図5.2.1再送タイムアウト時間 


 to the Index page