今日はTCPのヘッダについて書いていきます。
もくじ
1.TCPヘッダとは
TCPでデータを送る際は、送り先などの情報と、データ本体の両方を送る必要がある。
宅配便でいうと、宛先住所などを書いた送り状と、宅配する中身(荷物)そのものの2つが必要になるのと同じイメージ。
TCPも宅配便も、送り状だけ送っても意味はないし、中身だけでは宛先不明で送ることができないということだ。
TCPでは、送り先などの情報を「ヘッダ」と呼ばれる部分に埋め込む。
送信データは、ヘッダの情報をもとに、ネットワーク上を移動し、適切な宛先サーバ等に運ばれる。
2.TCPヘッダのフィールド一覧
TCPのヘッダは、フォーマットが決められており、ヘッダ最後尾の内容であるオプション部分以外は、固定長となっている。
フォーマットは以下のとおり。
名称 | 長さ (bit) |
備考 |
---|---|---|
送信元ポート番号 | 16 | |
宛先ポート番号 | 16 | |
シーケンス番号 | 32 | |
ACK番号 | 32 | |
データオフセット(データ長) | 4 | |
(未使用/予約) | 6 | 現在使われていないが、 枠だけ存在しているフィールド。 |
フラグ(コントロールビット) | 6 | |
ウィンドウサイズ | 16 | |
チェックサム | 16 | |
緊急ポインタ | 16 | |
オプション(パディング) | 可変長 | その他任意の制御情報を追加できる (ただし使用例は少ない) |
次に、上記の備考記載分以外の各フィールドについて、詳しく説明する。
3.各フィールドの説明
◎送信元ポート番号
パケットの送信元プログラムのポート番号。
パケットの宛先(通信相手)から応答が返ってきたときに、応答を受け取るポート番号でもある。
◎宛先ポート番号
通信相手の宛先プログラムのポート番号。
ちなみに、宛先ノードを特定する役割はIPアドレスやMACアドレスが担う(IPヘッダやMACヘッダで制御)。
そのため、TCPヘッダにはIPアドレスやMACアドレスの情報は無く、ポート番号の情報のみが記載される。
◎シーケンス番号
シーケンス番号は、今回のパケットの先頭位置にあるデータが、
送信データ全体のうち何バイト目にあたるかを表す。
そもそもパケットは、データの重さに応じて複数に分けて運ばれる。
そのため、宛先ノードに向かう送信途中で一部のパケットが喪失する恐れがある。
しかしシーケンス番号を利用すれば、受信側でデータの喪失を検知できるようになり、
送信側に再送を求めることが可能となる。
データ喪失の検知は以下のように行われる。
①受信側がデータを受信する。
②受信側は、これまでに届いているデータ本体の長さを計算する。
(パケット全体=ヘッダ+データ本体 であり、ヘッダ長は決まっているので簡単に計算可能)
③②で計算したデータの長さと、今回のパケットのシーケンス番号が何番かを確認し、整合性を確認する。
例えば、100バイト目まで受信し終わった状態で、次に届いたパケットのシーケンス番号が
・101番目の値であれば、正しく受信した
・201番目の値であれば、101~200番目のデータが喪失した
と、それぞれ判断できる。
このようにシーケンス番号は、通信データの正確性を求めるTCPにおいて、
重要な役割を果たすヘッダ値なのである。
◎ACK番号
データが何バイト目まで届いたかを、受信側から送信側に対して伝えるためのフィールド。
「ちゃんとここまで届いたよ」と応答することで、通信データの正確さを保てるようになっている。
なお、「ACK」はacknowledge(意味:認める)の略で、TCPの世界では「確認応答」という意味合いになる。
◎データオフセット(データ長)
パケット全体のうち、本体データの開始位置を示す。
すなわちヘッダの長さを通知するフィールドと言える。
ヘッダのフィールドは、2.TCPヘッダのフィールド一覧で記載した通りほとんど固定長だが、オプションフィールドのみ可変長となっている。
そのため、パケット全体のうち、どこまでがヘッダで、どこからがデータ本体なのかを明示してやる必要がある。
◎フラグ(コントロールビット)
長さ6ビットのフィールド。各ビットが以下6フラグの値を示している。
(0=無効、1=有効)
フラグ名 | 意味 | 説明 |
---|---|---|
URG | Urgent(緊急) | 後述の「緊急ポインタ」フィールドに有効値が入っているかどうか。 |
ACK | Acknowledge(承認) | 前述の「ACK番号」フィールドに有効値が入っているかどうか。 |
PSH | Push(引き上げる) | パケット受信後、すぐに上位アプリケーションプログラムにデータを引き渡すかどうか。 ※受信側では、パケット受信毎に受信データをプログラムに渡すと非効率なので、まずバッファに受信データを留め、ある程度データがたまってから一気にプログラムへ渡すようになっている。バッファに置かず、すぐにデータを連携したい場合に、このフラグを1にする。(ただし最近では技術進歩により、データは即時処理されることが普通なので、わざわざフラグを有効にすることはほとんどない) |
RST | Reset(リセット) | 1の場合、接続を強制終了する。異常終了した時など。 |
SYN | Synchronize(同期) | 1の場合、送信側・受信側で接続を確立する。 |
FIN | Finish(終了) | 1の場合、切断を示す。 |
上記6つのフラグのうち、よく使われる(有効になる)のは、
ACK、SYN、FINの3つである。
TCP通信では、いわゆる3ウェイハンドシェイク(※)にて通信を開始するが、
開始時に送るパケット、すなわち接続を確立するためのパケットは、SYNフラグが有効(1)になっている。
接続確立後、本格的にデータをやり取りする際は、ACKフラグを有効(1)にして、データ受信状況を相手ノードに伝えることとなる。
データの送受信を終え、切断する時には、FINフラグを有効(1)にして、相手ノードに切断を伝える。
※3ウェイハンドシェイクの詳細は以下の記事をご参照のこと。
◎ウィンドウサイズ
前提として、TCP通信は、相手ノードに確実にデータが届いたかを確認するために、前述のACK(確認応答)を行うことになっている。
しかし、パケットを1つ送るたびに相手ノードからの応答を待つとすると、通信に時間がかかってしまう。
そこで、送信側は受信側に向け、応答を待たずに次々とデータを送っていき、
時間差で届いた応答を後から確認、必要に応じて再送することとなっている。
だが、送信側がどんどんデータを送っていくと、受信側の処理が追い付かず、
最終的には、最初に来たデータから破棄していかざるを得なくなる。
せっかくのデータが不完全になるのを防ぐため、受信側は、
「これくらいの量なら、応答を待たずに先に送って良いよ(=受信側で処理できるよ)」
というデータサイズを、送信側に示すことになっている。
そのサイズがウィンドウサイズであり、本フィールドで提示するものである。
◎チェックサム
パケットに誤りがないかを検査するための、検査用データが入るフィールド。
具体的な値としては、「1の補数和の1の補数」が入る。
◎緊急ポインタ
前述のURGフラグが有効(1)の時に、緊急に処理すべきデータの開始位置を表す。
今回は以上!
参考文献
※リンクはAmazonです
戸根勤『ネットワークはなぜつながるのか 第2版』