【ネットワーク】TCPヘッダの中身を読み解く | 若手エンジニアのブログ

若手エンジニアのブログ

文系出身の若手女子エンジニアによる技術ブログ。
日々の経験や学びをアウトプットするためにブログを書いています。
バックエンド(Java+SpringFramework)を経てインフラエンジニアになりました。
今は育休中につき、本で勉強したことを中心にアウトプットしています。

今日はTCPのヘッダについて書いていきます。

 

もくじ

1.TCPのヘッダとは

2.TCPヘッダのフィールド一覧

3.各フィールドの説明

参考文献

 

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版

ネットワークはなぜつながるのか 第2版