トランスポート層の通信には、コネクション型のTCPとコネクションレス型のUDPがあります。
今回は、TCPについて説明します。
TCP
基本的な知識
TCPとは、トランスポート層におけるコネクション型の通信プロトコルのことです。
TCPでは、通信を開始する前に、宛先ホストとのコネクションを確立します。
コネクションを確立することで、データが通信が正常に完了したことやパケットの順番などを保証することができるため、信頼性を確保していると言えます。
TCPのヘッダは、以下のような構成になっています。
・送信元ポート番号/宛先ポート番号(各16ビット)
送信元と宛先のポート番号が設定される
・シーケンス番号(32ビット)
送信データに付与される連番の番号で、直前に受信したパケットの確認応答番号が設定される
・確認応答番号(32ビット)
データを受信したことを表す番号で、受信したパケットのシーケンス番号に受信したデータ長を加えた値が設定される
・データオフセット(4ビット)
ヘッダ長が設定される
・予約(6ビット)
使用される可能性がある予約範囲を示す(基本的には「0」が設定される)
・フラグ(6ビット)
以下のように構成されている、各種フラグが格納されたフィールド
URG | ACK | PSH | RST | SYN | FIN |
URG:緊急ポインタフィールド識別フラグ(緊急ポインタフィールドを使う場合「1」)
ACK:確認応答フラグ(コネクション確立要求以外は「1」)
PSH:受信したデータをすぐに上位のアプリケーションに渡すためのフラグ(すぐに渡す場合「1」)
RST:コネクションを強制的に切断するためのフラグ(コネクションを切断したい場合「1」)
SYN:同期フラグ(コネクション確立要求以外は「1」)
FIN:送信終了フラグ(コネクション解放要求であれば「1」)
・ウィンドウサイズ(16ビット)
連続で受信できるデータサイズを表している
・チェックサム(16ビット)
TCPヘッダとデータ部が正しいことをチェックするフィールド
・緊急ポインタ(16ビット)
フラグにおける「URG」が有効になっている場合に、緊急データの位置を示すフィールド
機器の異常や、受信データの過多などにより、通信の中断を知らせる場合に使われる
・オプション(可変長)
TCP通信におけるオプションを設定するフィールド
・パディング(可変長)
TCPヘッダが32ビットの整数倍になるように調整するためのフィールド
TCPの通信手順
TCPでは、「コネクションの確立」→「データ通信」→「コネクション切断」という手順で通信が実現されます。
ここでは、ホストA、ホストBでのTCP通信を解説します。
【コネクション確立】
コネクション確立は、ホストAとホストBの間で3回のやり取りが行われます。
これをスリーウェイハンドシェイクといいます。
①ホストAからのコネクション確立要求
②ホストBからのコネクション確立要求&確認応答
③ホストAにおける確認応答
要するに、双方からコネクション確立要求がされ、双方が確認応答をして、やっとコネクションが確立されるということです。
以下、スリーウェイハンドシェイクのイメージ図になります。
シーケンス番号の初期値は、乱数によってランダムに設定されます。
(ホストAのシーケンス番号の初期値:2000、ホストBのシーケンス番号の初期値:5000)
確認応答番号は、本来は「受信したパケットのシーケンス番号+受信データ長」であるが、コネクション確立と切断においては「受信したパケットのシーケンス番号+1」となります。
【データ通信】
コネクション確立後、データ送信側は「データ」を送信し、受信側はデータを受信したことを通知する「確認応答」を返信することで、データ通信を実現しています。
シーケンス番号や確認応答番号については、コネクション確立時のものを引き継ぎます。
そのため、データ通信開始時の送信側(ホストA)のシーケンス番号および確認応答番号は、ホストAの確認応答のときと同じ値になります。
(シーケンス番号:2001、確認応答番号:5001)
また、データ受信側(ホストB)の確認応答のシーケンス番号および確認応答番号は、以下の通りになります。
シーケンス番号:受信したデータの確認応答番号
確認応答番号:受信したデータのシーケンス番号+データサイズのバイト数
データ通信のイメージは、以下になります。
すべての通信において、ACKのビットを立てたまま、確認応答番号が増えていっていますね。
データをすべて送信するまで、このやり取りが繰り返されます。
ここで、連続送信について説明しておきます。
データパケットを1つずつ送信し、確認応答があってから次のデータパケットを送信する、という方法だと、非常に効率が悪いです。
そのため、確認応答を待たずに複数のデータパケットを送信し、後から複数の確認応答を受け取る、という方法でデータ通信が可能です。
TCPでは、この連続送信により、データ通信の効率を向上させています。
【コネクション切断】
データ通信完了後、双方が「FIN」を通知することで、コネクションが切断されます。
また、FINパケットを受信した時点で、まだ送信したデータが残っているときは、FINパケットを送り返す前にデータを送信し、その後FINパケットを送信します。
シーケンス番号や確認応答番号については、データ通信時のものを引き継ぎます。
そのため、コネクション切断時の送信側(ホストA)のシーケンス番号および確認応答番号は、ホストBの確認応答のときと同じ値になります。
(シーケンス番号:2401、確認応答番号:5001)
コネクション切断のイメージは、以下になります。
確認応答番号は、本来は「受信したパケットのシーケンス番号+受信データ長」であるが、コネクション確立と切断においては「受信したパケットのシーケンス番号+1」となります。
これで、コネクションは切断されます。
ウィンドウ制御
ウィンドウ制御とは、データ通信のところで説明した「連続送信」を実現するために、ウィンドウサイズによって通信を制御することです。
ウィンドウサイズとは、データを連続受信できる最大値のことで、受信側が送信側に通知します。
通信の流れとしては、以下の通りです。
①データ受信側からのウィンドウサイズの通知
②送信側からのデータの送信
③受信側からの確認応答
④②と③の繰り返し
言葉では理解し難いため、例として、以下の流れを図にしました。
送信側:ホストA
受信側:ホストB
ウィンドウサイズ:1500バイト
送信したいデータサイズ:3000バイト(500バイト×6パケット)
①ウィンドウサイズが通知される(1500バイト)
②ウィンドウサイズ分のデータを送信する(500バイト×3パケット)
③3パケットそれぞれに確認応答が送信される
④1パケット(500バイト)分の確認応答が届いたため、すぐに追加で1パケット(500バイト)を送信する
⑤追加で1パケット分の確認応答が届いたため、さらに追加で1パケット分を送信する
⑥追加で1パケット分の確認応答が届いたため、さらに追加で1パケット分を送信する(すべてのデータを送信完了)
⑦ ④の確認応答を送信する
⑧ ⑤の確認応答を送信する
⑨ ⑥の確認応答を送信する(すべてのデータを受信完了)
まずはウィンドウサイズ(受信できる最大値)分だけ受信し、受信が完了したら次々とデータを送信する、ということです。
(スライディングウィンドウ制御と呼ばれることもあります)
これにより、データ通信の効率を上げる「連続送信」を実現しています。
また、受信側は「一括応答確認」も可能です。
上記で説明したウィンドウ制御において、1パケットずつそれぞれに確認応答を送信するのではなく、ウィンドウサイズ分のデータが届いたら確認応答を1回だけ送信する、という方法です。
フロー制御
フロー制御とは、データ通信における受信側が、自身の状態を送信側に通知することで、送信を調整させることです。
TCPでは、受信不可能になった場合は、ウィンドウサイズを「0」に設定して通知します。
これをウィンドウフロー制御と言います。
受信可能になったら、改めてウィンドウサイズを通知することで、データ送信が再開されます。
コメント