3. Functional Specification - Part 1 (機能仕様 - 第1部)
本セクションには、TCPのコア技術仕様が含まれています:ヘッダー形式、用語、およびシーケンス番号メカニズム。
3.1. Header Format (ヘッダー形式)
TCPセグメント (TCP segments) は、インターネットデータグラム (internet datagrams) として送信されます。インターネットプロトコルヘッダーには、送信元および宛先ホストアドレスを含むいくつかの情報フィールドが含まれています [2]。TCPヘッダーは、インターネットヘッダーに続き、TCPプロトコル固有の情報を提供します。この分割により、TCP以外のホストレベルプロトコルの存在が可能になります。
TCPヘッダー形式
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
TCPヘッダー形式
注: 1つの目盛りは1ビット位置を表します
フィールド詳細説明
Source Port (送信元ポート): 16ビット
送信元ポート番号。
用途: 送信ホスト上の送信プロセスを識別します。
Destination Port (宛先ポート): 16ビット
宛先ポート番号。
用途: 受信ホスト上の受信プロセスを識別します。
Sequence Number (シーケンス番号): 32ビット
このセグメント内の最初のデータオクテットのシーケンス番号 (SYNが存在する場合を除く)。SYNが存在する場合、シーケンス番号は初期シーケンス番号 (Initial Sequence Number, ISN) であり、最初のデータオクテットはISN+1です。
重要なポイント:
- 各データバイトには一意のシーケンス番号があります
- SYNセグメントはISNを使用し、データはISN+1から始まります
- シーケンス番号空間: 0から2³² - 1
Acknowledgment Number (確認応答番号): 32ビット
ACK制御ビットが設定されている場合、このフィールドには、セグメントの送信者が受信を期待している次のシーケンス番号の値が含まれます。接続が確立されると、これは常に送信されます。
累積確認応答メカニズム:
- 確認応答番号Xは、X未満のすべてのバイトが受信されたことを示します
- X自体は含まれません
Data Offset (データオフセット): 4ビット
TCPヘッダー内の32ビットワードの数。これは、データがどこから始まるかを示します。TCPヘッダー (オプションを含む場合でも) は、32ビットの整数倍の長さです。
計算式:
ヘッダー長 (バイト) = Data Offset × 4
最小値: 5 (20バイト)
最大値: 15 (60バイト)
Reserved (予約済み): 6ビット
将来の使用のために予約されています。ゼロでなければなりません (MUST)。
Control Bits (制御ビット): 6ビット (左から右へ)
| フラグ | 正式名称 | 意味 |
|---|---|---|
| URG | Urgent | 緊急ポインターフィールドが有効 |
| ACK | Acknowledgment | 確認応答フィールドが有効 |
| PSH | Push | プッシュ機能 |
| RST | Reset | 接続をリセット |
| SYN | Synchronize | シーケンス番号を同期 |
| FIN | Finish | 送信者からのデータがこれ以上ない |
フラグの組み合わせの意味:
SYN = 1: 接続確立リクエスト
SYN + ACK = 1: 接続確立レスポンス
FIN = 1: 接続終了リクエスト
RST = 1: 異常な接続終了
PSH = 1: データを直ちにアプリケーション層にプッシュ
URG = 1: 緊急データが存在
Window (ウィンドウ): 16ビット
確認応答フィールドで示されるオクテットから始まる、このセグメントの送信者が受け入れる用意があるデータオクテットの数。
フロー制御:
- ウィンドウサイズ = 0: データの送信を停止
- ウィンドウサイズ > 0: ウィンドウサイズバイトまでのデータを送信可能
- 最大ウィンドウ: 65,535バイト (ウィンドウスケーリングオプションで拡張可能)
例:
ACK = 1000, Window = 5000
→ シーケンス番号1000-4999のデータを受信可能 (5000バイト)
Checksum (チェックサム): 16ビット
チェックサムフィールドは、ヘッダーとテキスト内のすべての16ビットワードの1の補数和の16ビット1の補数です。セグメントにチェックサムする奇数個のヘッダーおよびテキストオクテットが含まれている場合、最後のオクテットは右側にゼロでパディングされ、チェックサム目的で16ビットワードが形成されます。パディングはセグメントの一部として送信されません。チェックサムを計算する際、チェックサムフィールド自体はゼロに置き換えられます。
擬似ヘッダー (Pseudo Header):
チェックサムは、概念的にTCPヘッダーの前に付加される96ビットの擬似ヘッダーもカバーします。この擬似ヘッダーには、送信元アドレス、宛先アドレス、プロトコル、およびTCP長が含まれます。これにより、TCPは誤ってルーティングされたセグメントから保護されます。
+--------+--------+--------+--------+
| Source Address |
+--------+--------+--------+--------+
| Destination Address |
+--------+--------+--------+--------+
| zero | PTCL | TCP Length |
+--------+--------+--------+--------+
PTCL = 6 (TCPプロトコル番号)
TCP Length = TCPヘッダー長 + データ長 (オクテット単位)
チェックサム計算手順:
def calculate_tcp_checksum(pseudo_header, tcp_header, data):
# 1. チェックサムフィールドを0に設定
# 2. 擬似ヘッダー、TCPヘッダー、およびデータを結合
# 3. 16ビットワードとして合計
# 4. キャリーを下位16ビットに追加
# 5. 1の補数を取る
pass
Urgent Pointer (緊急ポインター): 16ビット
このフィールドは、このセグメントのシーケンス番号からの正のオフセットとして、緊急ポインターの現在の値を伝達します。緊急ポインターは、緊急データに続くオクテットのシーケンス番号を指します。このフィールドは、URG制御ビットが設定されたセグメントでのみ解釈されます。
使用例:
- Ctrl+C割り込み信号
- Telnet割り込みコマンド
- 優先処理を必要とする制御情報
例:
SEG.SEQ = 1000
URG Pointer = 10
→ 緊急データはシーケンス番号1010で終了
→ シーケンス番号1000-1009は緊急データ
Options (オプション): 可変
オプションは、TCPヘッダーの最後にスペースを占有する場合があり、長さは8ビットの倍数です。すべてのオプションは、チェックサムに含まれます。オプションは、任意のオクテット境界から始めることができます。オプションの形式には2つのケースがあります:
ケース1: 単一のオクテットのoption-kind ケース2: 1オクテットのoption-kind、1オクテットのoption-length、および実際のoption-dataオクテット
option-lengthは、option-kindとoption-lengthの2つのオクテット、およびoption-dataオクテットをカウントします。
重要: TCPはすべてのオプションを実装しなければなりません (MUST)。
現在定義されているオプション
| Kind (8進数) | Length | 意味 |
|---|---|---|
| 0 | - | オプションリストの終了 (End of Option List) |
| 1 | - | 無操作 (No-Operation) |
| 2 | 4 | 最大セグメントサイズ (Maximum Segment Size) |
オプション詳細
1. End of Option List (オプションリストの終了)
+--------+
|00000000|
+--------+
Kind=0
- このオプションコードは、オプションリストの終了を示します
- これは、Data Offsetフィールドに従ったTCPヘッダーの終了と一致しない場合があります
- 各オプションの終了ではなく、すべてのオプションの終了で使用されます
- オプションの終了がTCPヘッダーの終了と一致しない場合にのみ必要です
2. No-Operation (無操作)
+--------+
|00000001|
+--------+
Kind=1
- このオプションコードは、オプション間で使用できます (MAY)
- 例えば、後続のオプションの開始をワード境界に整列するため
- 送信者がこのオプションを使用することは保証されません
- 受信者は、ワード境界から始まらないオプションを処理する準備ができていなければなりません (MUST)
3. Maximum Segment Size (最大セグメントサイズ)
+--------+--------+---------+--------+
|00000010|00000100| max seg size |
+--------+--------+---------+--------+
Kind=2 Length=4
Maximum Segment Size Option Data: 16ビット
- このオプションが存在する場合、このセグメントを送信するTCPでの最大受信セグメントサイズを伝達します
- このフィールドは、初期接続リクエストでのみ送信しなければなりません (MUST) (つまり、SYN制御ビットが設定されたセグメント)
- このオプションが使用されない場合、任意のセグメントサイズが許可されます
MSS説明:
- デフォルトMSS = 536バイト (インターネットデフォルト)
- イーサネットの一般的なMSS = 1460バイト (1500 - 20 IPヘッダー - 20 TCPヘッダー)
- MSSはデータ部分のみを指し、TCP/IPヘッダーは含まれません
Padding (パディング): 可変
TCPヘッダーパディングは、TCPヘッダーが32ビット境界で終了し、データが32ビット境界で始まることを保証するために使用されます。パディングはゼロで構成されます。
3.2. Terminology (用語)
TCPの動作について議論する前に、いくつかの詳細な用語を導入する必要があります。TCP接続の維持には、いくつかの変数を記憶する必要があります。これらの変数は、伝送制御ブロック (Transmission Control Block, TCB) と呼ばれる接続レコードに格納されていると考えます。
TCBに格納される変数
TCBに格納される変数には、以下が含まれます:
- ローカルおよびリモートのソケット番号
- 接続のセキュリティと優先度
- ユーザーの送信および受信バッファーへのポインター
- 再送信キューおよび現在のセグメントへのポインター
- 送信および受信シーケンス番号に関連するいくつかの変数
送信シーケンス変数 (Send Sequence Variables)
| 変数 | 正式名称 | 説明 |
|---|---|---|
| SND.UNA | Send Unacknowledged | 送信未確認 (最も古い未確認シーケンス番号) |
| SND.NXT | Send Next | 送信次 (次に送信するシーケンス番号) |
| SND.WND | Send Window | 送信ウィンドウ |
| SND.UP | Send Urgent Pointer | 送信緊急ポインター |
| SND.WL1 | Segment Sequence Number | 最後のウィンドウ更新に使用されたセグメントシーケンス番号 |
| SND.WL2 | Segment Acknowledgment Number | 最後のウィンドウ更新に使用されたセグメント確認応答番号 |
| ISS | Initial Send Sequence Number | 初期送信シーケンス番号 |
受信シーケンス変数 (Receive Sequence Variables)
| 変数 | 正式名称 | 説明 |
|---|---|---|
| RCV.NXT | Receive Next | 受信次 (次に期待されるシーケンス番号) |
| RCV.WND | Receive Window | 受信ウィンドウ |
| RCV.UP | Receive Urgent Pointer | 受信緊急ポインター |
| IRS | Initial Receive Sequence Number | 初期受信シーケンス番号 |
シーケンス空間図
送信シーケンス空間 (Send Sequence Space)
1 2 3 4
----------|----------|----------|----------
SND.UNA SND.NXT SND.UNA
+SND.WND
1 - 確認応答された古いシーケンス番号
2 - 未確認データのシーケンス番号
3 - 新しいデータ送信が許可されるシーケンス番号
4 - まだ許可されていない将来のシーケンス番号
送信ウィンドウ: 図の3とラベル付けされたシーケンス空間の部分
受信シーケンス空間 (Receive Sequence Space)
1 2 3
----------|----------|----------
RCV.NXT RCV.NXT
+RCV.WND
1 - 確認応答された古いシーケンス番号
2 - 新しい受信が許可されるシーケンス番号
3 - まだ許可されていない将来のシーケンス番号
受信ウィンドウ: 図の2とラベル付けされたシーケンス空間の部分
現在のセグメント変数 (Current Segment Variables)
これらの変数は、現在のセグメントのフィールドから値を取得します:
| 変数 | 説明 |
|---|---|
| SEG.SEQ | セグメントシーケンス番号 |
| SEG.ACK | セグメント確認応答番号 |
| SEG.LEN | セグメント長 |
| SEG.WND | セグメントウィンドウ |
| SEG.UP | セグメント緊急ポインター |
| SEG.PRC | セグメント優先度値 |
接続状態 (Connection States)
接続は、その生涯の間に一連の状態を経過します。状態には、LISTEN, SYN-SENT, SYN-RECEIVED, ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT、および架空の状態CLOSEDが含まれます。
状態詳細説明
| 状態 | 説明 |
|---|---|
| LISTEN | 任意のリモートTCPおよびポートからの接続リクエストを待機していることを表します |
| SYN-SENT | 接続リクエストを送信した後、一致する接続リクエストを待機していることを表します |
| SYN-RECEIVED | 接続リクエストを受信および送信した後、接続リクエストの確認応答を待機していることを表します |
| ESTABLISHED | オープンな接続を表し、受信したデータをユーザーに配信できます。接続のデータ転送フェーズの通常の状態 |
| FIN-WAIT-1 | リモートTCPからの接続終了リクエスト、または以前に送信された接続終了リクエストの確認応答を待機していることを表します |
| FIN-WAIT-2 | リモートTCPからの接続終了リクエストを待機していることを表します |
| CLOSE-WAIT | ローカルユーザーからの接続終了リクエストを待機していることを表します |
| CLOSING | リモートTCPからの接続終了リクエストの確認応答を待機していることを表します |
| LAST-ACK | リモートTCPに以前に送信された接続終了リクエストの確認応答を待機していることを表します (その接続終了リクエストの確認応答を含む) |
| TIME-WAIT | リモートTCPがその接続終了リクエストの確認応答を受信したことを確認するために十分な時間が経過するのを待機していることを表します |
| CLOSED | 接続状態がまったくないことを表します (TCBが存在しない場合の状態を表すため、架空の状態) |
TCP接続状態図
+---------+ ---------\ active OPEN
| CLOSED | \ -----------
+---------+<---------\ \ create TCB
| ^ \ \ snd SYN
passive OPEN | | CLOSE \ \
------------ | | ---------- \ \
create TCB | | delete TCB \ \
V | \ \
+---------+ CLOSE | \
| LISTEN | ---------- | |
+---------+ delete TCB | |
rcv SYN | | SEND | |
----------- | | ------- | V
+---------+ snd SYN,ACK / \ snd SYN +---------+
| |<----------------- ------------------>| |
| SYN | rcv SYN | SYN |
| RCVD |<-----------------------------------------------| SENT |
| | snd ACK | |
| |------------------ -------------------| |
+---------+ rcv ACK of SYN \ / rcv SYN,ACK +---------+
| -------------- | | -----------
| x | | snd ACK
| V V
| CLOSE +---------+
| ------- | ESTAB |
| snd FIN +---------+
| CLOSE | | rcv FIN
V ------- | | -------
+---------+ snd FIN / \ snd ACK +---------+
| FIN |<----------------- ------------------>| CLOSE |
| WAIT-1 |------------------ | WAIT |
+---------+ rcv FIN \ +---------+
| rcv ACK of FIN ------- | CLOSE |
| -------------- snd ACK | ------- |
V x V snd FIN V
+---------+ +---------+ +---------+
|FINWAIT-2| | CLOSING | | LAST-ACK|
+---------+ +---------+ +---------+
| rcv ACK of FIN | rcv ACK of FIN |
| rcv FIN -------------- | Timeout=2MSL -------------- |
| ------- x V ------------ x V
\ snd ACK +---------+delete TCB +---------+
------------------------>|TIME WAIT|------------------>| CLOSED |
+---------+ +---------+
TCP接続状態図
イベントと状態遷移
TCP接続は、イベントに応答して1つの状態から別の状態に進行します。イベントには以下が含まれます:
- ユーザー呼び出し: OPEN, SEND, RECEIVE, CLOSE, ABORT, STATUS
- 到着するセグメント: 特に、SYN, ACK, RST, FINフラグを含むセグメント
- タイムアウト: 再送信タイムアウト、TIME-WAITタイムアウトなど
注意: 状態図は要約にすぎず、完全な仕様として単独で使用することはできません。状態変化、それらをトリガーするイベント、および結果として生じるアクションのみを示していますが、エラー条件や状態変化に関連しないアクションは示されていません。
3.3. Sequence Numbers (シーケンス番号)
基本概念
TCP設計における基本的な概念は、TCP接続を介して送信されるすべてのデータオクテットにシーケンス番号があることです。すべてのオクテットがシーケンス付けされているため、それぞれを確認応答できます。採用されている確認応答メカニズムは累積的 (cumulative) であるため、シーケンス番号Xの確認応答は、Xまで (Xを含まない) のすべてのオクテットが受信されたことを示します。
このメカニズムにより、再送信が存在する場合の単純な重複検出が可能になります。セグメント内のオクテットの番号付けは、ヘッダーの直後の最初のデータオクテットが最も低く番号付けされ、後続のオクテットは連続して番号付けされます。
シーケンス番号空間
重要な事実: 実際のシーケンス番号空間は有限ですが、非常に大きいです。この空間は0から2³² - 1の範囲です。
モジュロ演算 (Modulo Arithmetic): 空間が有限であるため、シーケンス番号を扱うすべての演算は、モジュロ2³²で実行しなければなりません (MUST)。この符号なし演算は、シーケンス番号が2³² - 1から0に循環するときの関係を保持します。コンピューターのモジュロ演算にはいくつかの微妙な点があるため、そのような値の比較をプログラミングする際には細心の注意を払う必要があります (SHOULD)。
表記規則:
- 記号
=<は「以下」を意味します (モジュロ2³²)
シーケンス番号比較
TCPが実行しなければならない典型的なシーケンス番号比較には、以下が含まれます:
- 確認応答が送信されたがまだ確認応答されていないシーケンス番号を参照していることを判断する
- セグメントによって占有されるすべてのシーケンス番号が確認応答されたことを判断する (例えば、再送信キューからセグメントを削除するため)
- 着信セグメントに期待されるシーケンス番号が含まれていることを判断する (つまり、セグメントが受信ウィンドウと「重複」している)
送信シーケンス番号処理
データ送信に応答して、TCPは確認応答を受信します。確認応答を処理するには、以下の比較が必要です:
SND.UNA = 最も古い未確認シーケンス番号
SND.NXT = 次に送信するシーケンス番号
SEG.ACK = 受信TCPからの確認応答 (受信TCPが期待する次のシーケンス番号)
SEG.SEQ = セグメントの最初のシーケンス番号
SEG.LEN = セグメント内のデータが占有するオクテット数 (SYNとFINをカウント)
SEG.SEQ+SEG.LEN-1 = セグメントの最後のシーケンス番号
受け入れ可能なACK (Acceptable ACK):
新しい確認応答 (「受け入れ可能なACK」と呼ばれる) は、以下の不等式を満たす確認応答です:
SND.UNA < SEG.ACK ≤ SND.NXT
再送信キュー上のセグメントは、そのシーケンス番号と長さの合計が着信セグメント内の確認応答値以下である場合、完全に確認応答されます。
例:
SND.UNA = 1000 (最も古い未確認)
SND.NXT = 2000 (次に送信)
SEG.ACK = 1500を受信
チェック: 1000 < 1500 ≤ 2000 ✓ (受け入れ可能)
SEG.ACK = 2500を受信
チェック: 1000 < 2500 ≤ 2000 ✗ (受け入れ不可、未送信データを確認応答)
受信シーケンス番号処理
データを受信するとき、以下の比較が必要です:
RCV.NXT = 着信セグメントで期待される次のシーケンス番号、
受信ウィンドウの左端または下端
RCV.NXT+RCV.WND-1 = 着信セグメントで期待される最後のシーケンス番号、
受信ウィンドウの右端または上端
SEG.SEQ = 着信セグメントが占有する最初のシーケンス番号
SEG.SEQ+SEG.LEN-1 = 着信セグメントが占有する最後のシーケンス番号
セグメントの受け入れ可能性テスト
セグメントは、そのシーケンス番号がウィンドウ内にある場合にのみ受け入れ可能と見なされます。テストは、セグメント長とウィンドウサイズに依存します:
| セグメント長 | ウィンドウサイズ | 受け入れ可能性テスト |
|---|---|---|
| 0 | 0 | SEG.SEQ = RCV.NXT |
| 0 | >0 | RCV.NXT ≤ SEG.SEQ < RCV.NXT+RCV.WND |
| >0 | 0 | 受け入れ不可 |
| >0 | >0 | RCV.NXT ≤ SEG.SEQ < RCV.NXT+RCV.WND または RCV.NXT ≤ SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND |
説明:
- ゼロ長セグメントの最初のテストは、SEG.SEQから始まりシーケンス空間を占有しない仮想セグメントのテストと見なすことができます
- RCV.WNDがゼロの場合、データは受け入れられませんが、空間を占有しないセグメントは受け入れられます
実用的なコード例:
def is_segment_acceptable(seg_seq, seg_len, rcv_nxt, rcv_wnd):
"""セグメントが受け入れ可能かどうかをチェック"""
if seg_len == 0:
if rcv_wnd == 0:
return seg_seq == rcv_nxt
else:
return rcv_nxt <= seg_seq < rcv_nxt + rcv_wnd
else: # seg_len > 0
if rcv_wnd == 0:
return False
else:
# セグメントの開始または終了がウィンドウ内
start_in_window = rcv_nxt <= seg_seq < rcv_nxt + rcv_wnd
end_in_window = rcv_nxt <= seg_seq + seg_len - 1 < rcv_nxt + rcv_wnd
return start_in_window or end_in_window
初期シーケンス番号の選択 (ISN)
初期シーケンス番号 (ISN) の選択は非常に重要です。TCPは、古い接続セグメントが新しい接続の一部として誤認されることを避けるために、クロックベースのISN生成器を使用しなければなりません (MUST)。
ISN生成の推奨事項:
- ISNは4マイクロ秒ごとに1ずつ増加すべきです (SHOULD)
- ISNは約4.55時間の周期を持ちます
- 新しい接続のISNは、古い接続のISNとは異なるべきです (SHOULD)
セキュリティ上の考慮事項:
- 現代の実装は、より安全なISN生成アルゴリズムを使用すべきです (SHOULD) (RFC 6528)
- シーケンス番号予測攻撃を防止
重要な概念まとめ
TCPヘッダー構造
- 固定20バイトヘッダー: すべてのコアフィールドを含む
- 可変長オプション: 最大40バイト
- チェックサムは擬似ヘッダーをカバー: 追加のエラー検出を提供
シーケンス番号メカニズム
- バイトごとの番号付け: 各データバイトに一意のシーケンス番号
- 累積確認応答: 確認応答番号は、それより小さいすべてのバイトが受信されたことを示します
- モジュロ2³²演算: シーケンス番号空間は循環的
接続状態
- 11の状態: CLOSEDからESTABLISHED、そして再びCLOSEDへ
- イベント駆動: ユーザー呼び出し、セグメント到着、タイムアウトが状態遷移をトリガー
- 3ウェイハンドシェイク: SYN → SYN-ACK → ACK
- 4ウェイクローズ: FIN → ACK → FIN → ACK
TCB変数
- 送信変数: SND.UNA, SND.NXT, SND.WNDなど
- 受信変数: RCV.NXT, RCV.WNDなど
- ウィンドウ管理: フロー制御のコア
次のセクション: 3.4-3.9 Connection Management & Event Processing (接続管理とイベント処理) - 接続確立、終了、データ通信、およびイベント処理の詳細仕様