Network Working Group
Request for Comments: 1122
Internet Engineering Task Force
R. Braden, Editor
October 1989

Requirements for Internet Hosts -- Communication Layers

4.2 転送制御プロトコル -- TCP

4.2.1 導入

転送制御プロトコル TCP [TCP:1] は、インターネットスイートの基本的な仮想回線トランスポートプロトコルである。TCP は信頼性があり順序正しい、オクテット (8 ビットバイト) の全二重ストリームの送信を提供する。TCP は、信頼性のあるコネクション型トランスポートサービス、例えばメール (SMTP)、ファイル転送 (FTP)、仮想端末サービス (Telnet) 等を必要とするアプリケーションによって使用される。これらのアプリケーション層プロトコルに対する要件は、[INTRO:1] で規定されている。

4.2.2 プロトコルウォークスルー

4.2.2.1 よく知られたポート: RFC-793 セクション 2.7

DISCUSSION:
TCP は、0 〜 255 の範囲のポート番号を "よく知られた" ポートとして予約し、そのポートはインターネット全体で標準化されているサービスにアクセスするために使用される。ポート空間の残りは、アプリケーションプロセスに自由に割り当てることができる。現在のよく知られたポート定義は、"番号割り当て" [INTRO:6] というタイトルの RFC で一覧化されている。新しいよく知られたポートを定義するための必要条件は、新しい実装を可能にするために提案されたサービスを、十分詳細に RFC でドキュメント化することである。

幾つかのシステムは、TCP ポート空間、予約ポートの三つ目の区分を追加することによって、この規定を拡張している。それは通常、オペレーティングシステム特有のサービスとして使用される。例えば予約されたポートは、256 からシステムに依存する上限値の間にあるかもしれない。幾つかのシステムは更に、それらのポートの値で TCP コネクションをオープンすることを特権ユーザにのみ許可することによって、よく知られ、予約されたポートを保護することを選択する。これは、全てのホストがそれらの低い番号のポートをこの方法で保護するとは仮定しない限り、完全に効率的である。

4.2.2.2 プッシュの使用: RFC-793 セクション 2.8

アプリケーションが、一連の SEND 呼び出しを PUSH フラグを設定せずに発行する時、TCP はそれを送信せずに、内部でデータを集めてもよい (MAY)。同様に、PSH ビットの無い一連のセグメントを受信した時、TCP は受信するアプリケーションには渡さずに、内部的にデータをキューイングしてもよい (MAY)。

PSH ビットはレコードマーカではなく、セグメント境界には依存しない。あり得る最長のセグメントを送信するために、送信側はデータをパケット化する時、継続する PSH ビットを破棄すべきである (SHOULD)。

TCP は、SEND 呼び出し上で PUSH フラグを実装してもよい (MAY)。もし PUSH フラグが実装されていなければ、送信側 TCP は (1) データをいつまでもバッファに溜めこんではならず、(2) 最後にバッファ溜めたセグメントに PSH ビットを設定しなければならない (MUST) (例えば、キューイングされた送信すべきデータがもう存在しないとき)。

RFC-793 のページ 48, 50, 74 での議論は、受信した PSH フラグをアプリケーション層に渡さなければならないことを誤って意味している。受信した PSH フラグをアプリケーション層に渡すことは、現在オプション (OPTIONAL) である。

アプリケーションプログラムは、通信デッドロックを避けるためにデータの配送を強制する必要があるときは常に、論理的に SEND 呼び出しで PUSH フラグを設定する必要がある。しかしパフォーマンスを向上するために (セクション 4.2.3.4 参照)、TCP は可能であれば常に最大長のセグメントを送信すべきである (SHOULD)。

DISCUSSION:
SEND 呼び出しで PUSH フラグを実装していない場合、例えば、アプリケーション/TCP インタフェースが純粋なストリーミングモデルを使用している場合、効率的なサイズのセグメントを生成するために小さなデータフラグメントを集める責任は、部分的にアプリケーション層が負う。

通常、対話型アプリケーションプロトコルは、各コマンドや応答シーケンスで、少なくとも最後の SEND 呼出しでは PUSH フラグを設定しなければならない。FTP のような大量転送プロトコルは、ファイルの最後のセグメントや、バッファのデッドロックを避ける必要がある場合に PUSH フラグを設定すべきである。

受信側では、PSH ビットにより、バッファに溜まったデータをアプリケーションに強制的に配送する (たとえバッファが一杯になるまで受信していなくても)。逆に PSH ビットを付与しないことは、アプリケーションプロセスを呼び起こす不要な呼び出しを避けるために使用できる。これは大規模なタイムシェアリングホストにとって、重要なパフォーマンスの効率化となりえる。PSH ビットを受信側アプリケーションに渡すことにより、アプリケーション内で同様な効率化が可能になる。

4.2.2.3 ウィンドウサイズ: RFC-793 Section 3.1

ウィンドウサイズは符号無し整数として扱わなければならない (MUST)。さもなくば大きなウィンドウサイズは負のウィンドウとして見え、TCP は動かないだろう。実装体はコネクションレコード中の送受信ウィンドウサイズに対して 32 ビットフィールドを確保し、全てのウィンドウ算出を 32 ビットで行うことが推奨される (RECOMMENDED)。

DISCUSSION:
TCP ヘッダのウィンドウフィールドは、高速で遅延の大きいパスでは小さ過ぎることが判明している。ウィンドウサイズを拡張するために、実験的な TCP オプションが定義されている。例として [TCP:11] を参照されたい。そのような拡張の採用を見越して、TCP 実装者はウィンドウを 32 ビットとして扱うべきである。

4.2.2.4 緊急ポインタ: RFC-793 セクション 3.1

二番目のセンテンスは誤りである。緊急ポインタは、緊急データのシーケンス中の最終オクテット (最終 + 1 ではない) のシーケンス番号を指す。ページ 56 (最後のセンテンス) の説明が正しい。

TCP は、如何なる長さの緊急データのシーケンスもサポートしなければならない (MUST)。

TCP は緊急ポインタを受信し、前に未処理の緊急データが無い場合、あるいは緊急ポインタがデータストリームの先を指している場合は必ず、アプリケーション層に非同期に通知しなければならない (MUST)。アプリケーションが、どの位コネクションから読むべき緊急データが残っているかを知るための方法、あるいは少なくとも緊急データをもっと読むべきか否かを決めるための方法が存在しなければならない (MUST)。

DISCUSSION:
緊急メカニズムはどんなアプリケーションでも使用してよいが、通常それは "中断" タイプのコマンドを Telnet プログラムに送信するために使用される ([INTRO:1] の "Telnet 同期シーケンスの使用" セクション参照)。

非同期の、あるいは "帯域外" 通知により、アプリケーションは "緊急モード" に入り、TCP コネクションからデータを読むことができる。これにより、通常の入力バッファが未処理のデータで一杯になったアプリケーションに、制御コマンドを送信することが可能になる。

IMPLEMENTATION:
セクション 4.2.4.1 で規定されている一般的な ERROR-REPORT() 呼び出しは、緊急データの到着をアプリケーションに通知することができるメカニズムである。

4.2.2.5 TCP オプション: RFC-793 セクション 3.1

TCP は如何なるセグメント中の TCP オプションも受信できなければならない (MUST)。TCP は、実装していない如何なる TCP オプションも、異常無く無視しなければならず (MUST)、オプションは長さフィールドを持つ (将来定義されるだろう全ての TCP オプションは、長さフィールドを持つ) と仮定する。TCP は、不正なオプション長 (例えば 0) を、クラッシュせずに処理する準備ができていなければならない (MUST)。提案されている手続きは、コネクションをリセットして理由をログに採ることである。

4.2.2.6 最大セグメント長オプション: RFC-793 セクション 3.1

TCP は、最大セグメント長オプション [TCP:4] の受信と送信の両方を実装しなければならない (MUST)。

TCP は、受信 MSS (最大セグメント長) がデフォルトの 536 でない場合、全ての SYN セグメントで MSS オプションを送信すべきである (SHOULD)。また、常に MSS オプションを送信してもよい (MAY)。

もしコネクション設定時に MSS オプションを受信しなければ、TCP は送信 MSS を 536 (576-40) のデフォルト値であると仮定しなければならない (MUST)。[TCP:4]

TCP が実際に送信するセグメントの最大長、"有効送信 MSS" は送信 MSS (それは、リモートホストにおける利用可能な組立バッファ長を反映している) や、IP 層で許された最大長より小さくなければならない (MUST)。

  Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize

上記は、

MSS オプションで送信される MSS 値は、以下の値以下でなければならない。

  MMS_R - 20

MMS_R は受信 (組立) 可能なトランスポート層メッセージの最大長である。TCP は、MMS_R と MMS_S を IP 層から獲得する。セクション 3.4 の一般的な呼び出し GET_MAXSIZES を参照されたい。

DISCUSSION:
TCP セグメント長の選択はパフォーマンスに強く影響を及ぼす。セグメントが大きければ、ヘッダサイズや、より多くのデータバイトでデータグラム毎の処理オーバヘッドを減らすことによってスループットが増す。しかし、もしパケットが大き過ぎて IP 分割を引き起こし、フラグメントが損失したら、効率はひどく落ちるだろう。[IP:9]

幾つかの TCP 実装は、宛先ホストが接続されたネットワーク上にない場合に限り MSS オプションを送信する。しかし通常、TCP 層はこれを決めるために適切な情報を持っていないかもしれない。よって、インターネットパスにおいて適切な MTU を決定する仕事は IP 層に委ねる方が望ましい。従って、TCP は (もし 536 でなければ) 常にオプションを送信し、IP 層は 3.3.33.4 で規定されているように MMS_R を決定することを推奨する。そうすれば、MTU を計測するための IP 層メカニズムがの提案された時、TCP を変更せずに IP 層を修正できる。

4.2.2.7 TCP チェックサム: RFC-793 セクション 3.1

UDP チェックサム (セクション 4.1.3.4 参照) とは異なり、TCP チェックサムはオプションではない。送信側はチェックサムを生成しなければならず (MUST)、受信側はそれをチェックしなければならない (MUST)。

4.2.2.8 TCP コネクション状態遷移図: RFC-793 セクション 3.2, ページ 23

この図には幾つかの問題がある。

  1. ページ 68 と図 8 に合意するには、SYN-SENT から SYN-RECV への矢印には "snd SYN,ACK" というラベルが付くはずである。

  2. 受動的オープン (テキストページ 70 参照) 後に RST 受信という条件下で、SYN-RCVD 状態から LISTEN 状態への矢印があり得る。

  3. FIN-WAIT-1 から TIME-WAIT 状態に直接遷移することがあり得る (規約のページ 75 参照)。

4.2.2.9 初期シーケンス番号選択: RFC-793 セクション 3.3, ページ 27

TCP は、初期シーケンス番号の規定されたクロック駆動選択を使用しなければならない (MUST)。

4.2.2.10 同時オープンの試み: RFC-793 セクション 3.4, ページ 32

図 8 にはエラーがある。7 行目のパケットは 5 行目のパケットと同じはずである。

TCP は、同時オープンの試みをサポートしなければならない (MUST)。

DISCUSSION:
もし二つのアプリケーションがお互いに同時に接続することを試みたら、コネクションは 2 本ではなく 1 本しか生成されないことは、時々実装者を驚かせる。これは意図的な設計決定であった。これを "修正" しようとしてはならない。

4.2.2.11 古い重複 SYN からの回復: RFC-793 セクション 3.4, ページ 33

TCP 実装は、受動的 OPEN か能動的 OPEN のいずれの結果でコネクションが SYN_RCVD 状態に達したかを憶えていなければならない (MUST) ことに注意されたい。

4.2.2.12 RST セグメント: RFC-793 セクション 3.4

TCP は、受信した RST セグメントがデータを含むことを可能にすべきである (SHOULD)。

DISCUSSION:
符号化されて RST の原因を説明している ASCII テキストを、RST セグメントに含められることが提案されている。そのようなデータについては、まだ標準が確立されていない。

4.2.2.13 コネクションのクローズ: RFC-793 セクション 3.5

TCP コネクションは、二つの方法で終了してもよい。(1) FIN ハンドシェークを使用した TCP クローズシーケンス。(2) 一つ以上の RST セグメントが送信されて、コネクション状態が即座に破棄される "アボート" 。もし TCP コネクションがリモートサイトによりクローズされたら、コネクションが正常にクローズされたかアボートされたかをローカルアプリケーションに通知しなければならない (MUST)。

正常な TCP クローズシーケンスは、バッファに溜まったデータを確実に両方向に配送する。TCP コネクションの二つの方向はそれぞれ独立してクローズされるので、コネクションが "半クローズ"、すなわち片方向しかクローズされないことはあり得る。そしてホストは、半クローズコネクション上で、オープン方向にデータを送信し続けることが許されている。

ホストは、"半二重" の TCP クローズシーケンスを実装してもよい (MAY)。その場合、CLOSE を呼び出したアプリケーションは、そのコネクションからデータを読み続けることができない。もし、そのようなホストが、受信データがまだ TCP で未処理の間に CLOSE 呼び出しを発行したり、または CLOSE が呼び出された後に新しいデータが受信されたら、TCP はデータが消失したことを示すために RST を送信すべきである (SHOULD)。

コネクションが能動的にクローズされた場合、TCP は 2×MSL (最大セグメント生存時間) の時間だけ TIME-WAIT 状態に留まらなければならない (MUST)。しかし TCPは、以下の条件下で TIME-WAIT 状態から直接コネクションを再オープンして、リモート TCP からの新しい SYN を受け入れてもよい (MAY)。

  1. 前のコネクションの化身で使用された最も大きいシーケンス番号よりも大きい初期シーケンス番号を、新しいコネクションに対して割り当てる。

  2. もし SYN が古い重複であることが判明したら TIME-WAIT 状態に戻る。

DISCUSSION:
TCP の全二重データ保護クローズは、類似した ISO トランスポートプロトコル TP4 には含まれない機能である

恐らく、ある特定のオペレーティングシステムの I/O モデルに合わないため、あるシステムは半クローズのコネクションを実装しなかった。これらのシステムでは、一度アプリケーションがクローズを呼び出したら、そのコネクションから入力データを読みこむことができない。これは "半二重" TCP クローズシーケンスと呼ばれる。

TCP の上品なクローズアルゴリズムは、2×MSL のタイムアウト時間すなわち 4 分間、コネクション状態がコネクションの (少なくとも) 一方の終端で定義されたまま残る必要がある。この間、コネクションを定義する (リモートソケットとローカルソケットの) 組み合わせはビジーであり、再利用することができない。指定ポートの組み合わせが占有されている時間を短くするために、幾つかの TCP は TIME-WAIT 状態で新しい SYN の受け入れを許可している。

4.2.2.14 データ通信: RFC-793 セクション 3.7, ページ 40

RFC793 が書かれてから、効率的なデータ通信を達成するための TCP アルゴリズムに関して多大な作業があった。現ドキュメントの後半のセクションは、いつデータを送信するか (セクション 4.2.3.4)、いつ肯定応答を送信するか (セクション 4.2.3.2)、いつウィンドウを更新するか (セクション 4.2.3.3) を決定するために必要な、あるいは推奨される TCP アルゴリズムについて説明している。

DISCUSSION:
ある重要なパフォーマンスの問題は、"ばかげたウィンドウ症候群" あるいは "SWS" [TCP:5] である。ウィンドウの変化が永続的なパターンで小さく増加すると、結果的に極端に貧弱な TCP パフォーマンスを招く。SWS を回避するアルゴリズムは、送信側 (セクション 4.2.3.4) と受信側 (セクション 4.2.3.3) の両方について、以降で説明している。

簡単に言うと、SWS は受信側が新しい受信バッファ空間がデータ受信で利用可能になる時に必ずウィンドウの右端を拡大し、送信側がデータをさらに送信する [TCP:5] ために、小さいか否かに関わらずウィンドウを増加することによって引き起こされる。その結果、たとえ送信側と受信側の両方が、そのコネクションに対して大きなバッファ空間を持っていたとしても、小さなデータセグメントを送信するパターンに固定化される可能性がある。SWS は大量のデータを送信する間にのみ発生し得る。もしコネクションが無活動状態になったら、その問題は消えるだろう。それは、ウィンドウ管理の典型的で簡単な実装により引き起こされるが、以下に示す送信側と受信側のアルゴリズムによって、それは回避されるだろう。

もう一つの重要な TCP パフォーマンスの問題は、幾つかのアプリケーション、特に一度に 1 文字のホストにリモートログインにおいて、1 オクテットのデータセグメントのストリームを送信する傾向がある。デッドロックを回避するために、そのようなアプリケーションからの TCP SEND 呼び出しは全て、アプリケーションによって明示的に、さもなくば TCP によって暗黙的に "push" を指定しなければならない。その結果、各々 1 データオクテットを含む TCP セグメントのストリームになるかもしれない。それはインターネットを非常に非効率的に使用させ、インターネット輻輳の一因となる。セクション 4.2.3.4 で規定されている Nagle アルゴリズムは、この問題に対する簡単で効果的な解決方法を提供する。それは、Telnet コネクション上で文字を凝集する効果を実際に持つ。これは単一文字をエコーするのに慣れたユーザを驚かせるかもしれないが、ユーザの受けは問題になっていない。

Nagle アルゴリズムと送信 SWS 回避アルゴリズムは、パフォーマンスの改善に補助的な役割を果たす。Nagle アルゴリズムは、送信すべきデータが少ししか増えない小さいセグメントの送信を防ぎ、SWS 回避アルゴリズムは、小さなセグメントによってウィンドウの右端を少し増やすことを防ぐ。

軽率な実装体は、受信したデータセグメントにつき 2 個以上の肯定応答セグメントを送信するかもしれない。例えば、受信側が全てのデータセグメントに対して即座に肯定応答を返すと仮定する。その後、アプリケーションプログラムがデータを消費して、利用可能な受信バッファ空間を再び増やすとき、受信側は送信側のウィンドウを更新するために 2 個目の肯定応答を送信するかもしれない。極端なケースは、リモートログインサービスのために Telnet プロトコルを使用した TCP コネクション上の単一文字セグメントで発生する。幾つかの実装体で、1 文字の各入力セグメントにより 3 個の返却セグメントが生成されることが見られる。それぞれ、(1) 肯定応答 (2) ウィンドウの 1 バイト加算 (3) エコーされた文字である。

4.2.2.15 再送タイムアウト: RFC-793 セクション 3.7, ページ 41

RFC793 で提案されている再送タイムアウトのためのアルゴリズムは、不適切であることが知られている。以下の再送タイムアウトの計算セクション 4.2.3.1 参照。

インターネット輻輳と TCP 再送の安定性に関する Jacobson [TCP:7] による最近の作業により、"スロースタート" を "輻輳回避" と結びつけた送信アルゴリズムが作成された。TCP はこのアルゴリズムを実装しなければならない (MUST)。もし再送されたパケットが元のパケットと同じならば (それは、データ境界が変更されていないだけでなく、ヘッダのウィンドウと確認フィールドも変更されていないことを暗黙的に意味する)、同じ IP 識別子フィールドを使用してもよい (MAY)。(セクション 3.2.1.5 参照)

IMPLEMENTATION:
ある TCP 実装者は、データストリームを "パケット化" する、すなわち元のセグメントを送信し、それが確認されるまでこれらのセグメントを "再送キュー" にキューイングする時、セグメント境界を取り出すことを選択した。もう一つの設計は (より簡単かもしれない)、各データを送信または再送する時までパケット化することを先延ばしにすることである。それにより、セグメント再送キューが存在しない。

セグメント再送キューの実装において、最初の再送タイムアウトが発生したときに、肯定応答を待っているセグメントを再パケット化することによって TCP パフォーマンスが向上するかもしれない。すなわち、合った出力セグメントが、一つの最大長のセグメントにまとめられ、新しい IP 識別子値が付与される。そして TCP は、このまとめたセグメントが確認されるまで再送キューに保持する。しかし、もし再送キューにある最初の二つのセグメントが、一つの最大長セグメントのサイズを超えるならば、TCP は元の IP 識別子フィールドを使用して、最初のセグメントだけを再送するだろう。

4.2.2.16 ウィンドウ管理: RFC-793 セクション 3.7, ページ 41

TCP 受信側はウィンドウを縮小、すなわちウインドウの右端を左側に動かすべきではない (SHOULD NOT)。しかし、送信側 TCP はウィンドウ縮小に対して頑強でなければならない (MUST)。それが原因で、"使用可能なウィンドウ" (セクション 4.2.3.4 参照) が負の値になるかもしれない。

もしこれが起きたら、送信側は新しいデータを送信すべきでない (SHOULD NOT) が、SND.UNA と SND.UNA+SND.WND の間の古い未確認のデータを正常に再送すべきである (SHOULD)。送信側は SND.UNA+SND.WND を超える古いデータも再送してよい (MAY) が、もしウィンドウの右端を超えたデータが確認されていなければ、そのコネクションをタイムアウトすべきではない (SHOULD NOT)。もしウィンドウが 0 に縮小されたら、TCP は標準の方法で (次のセクション参照) プローブしなければならない (MUST)。

DISCUSSION:
もし大きなウィンドウで送信した直後にウィンドウが縮小したら、多くの TCP 実装体は混乱する。TCP はデータグラムが再順序付けられる可能性があるにもかかわらず、最も最近のウィンドウ更新を選択するための検出能力を持っていることに注意されたい。結果的に、シーケンス番号も確認番号も増えないならば、前に申し出たものよりも小さいウィンドウでウィンドウを更新することを無視してもよい。

4.2.2.17 ゼロウィンドウのプローブ: RFC-793 セクション 3.7, ページ 42

(申し出された) ゼロウィンドウのプローブは、サポートしなければならない (MUST)。

TCP は申し出された受信ウィンドウをずっと閉じたままにしてもよい (MAY)。受信側 TCP が、プローブセグメントの応答で肯定応答を送信し続ける限り、送信側 TCP はコネクションをオープンしたままにしなければならない (MUST)。

DISCUSSION:
データを含まない ACK (肯定応答) セグメントは、TCP によって確実に送信されるとは限らないことを憶えておくことは極めて重要である。もしゼロウィンドウプローブがサポートされていなければ、ウィンドウを再びオープンする ACK セグメントが消失した時、そのコネクションが永久にハングアップするかもしれない。

ゼロウィンドウのオープン遅延は通常、受信側アプリケーションが自分の TCP からデータを取ることを止めるときに発生する。例えば、プリンタデーモンアプリケーションについて考えれば、プリンタの紙切れが原因で止められる。

送信側ホストは、ゼロウィンドウプローブが再送タイムアウト期間中 (セクション 4.2.2.15 参照) に存在するとき、まず始めにゼロウィンドウプローブを送信すべきである (SHOULD)。そして、継続的なプローブ間の間隔を指数的に増やすべきである (SHOULD)。

DISCUSSION:
この手続きは、もしゼロウィンドウ状態がウィンドウを開ける更新を含んでいる ACK セグメントの消失によるものならば、遅延を最小化する。ここでは規定されないが、ある最大の時間間隔を持つ指数的なバックオフが推奨される。この手続きは再送アルゴリズムと同様であり、実装体に二つの手続きを統合することは可能かもしれない。

4.2.2.18 受動的 OPEN 呼び出し: RFC-793 セクション 3.8

受動的 OPEN 呼び出しは、LISTEN 状態で新しいコネクションレコードを生成するか、エラーを返却する。それは、以前に生成されたコネクションレコードに何ら影響を及ぼしてはならない (MUST NOT)。

複数の共同作業ユーザをサポートする TCP は、同じローカルポートを持つコネクションブロックが、SYN-SENT か SYN-RECEIVED 状態にある間に、アプリケーションがそのポートを LISTEN することを機能的に可能にする OPEN 呼び出しを提供しなければならない (MUST)。

DISCUSSION:
幾つかのアプリケーション (例えば SMTP サーバ) は、同時に複数のコネクション確立の試みを処理する必要があるかもしれない。以前のコネクション確立の試みが 3 方向ハンドシェークを行うのと同時に、新しいコネクションをリッスンする手段を提供することによって、コネクション確立の試みが失敗する可能性が減る。

IMPLEMENTATION:
同時オープンの許容可能な実装体は、複数の受動的 OPEN 呼び出しを許してもよい。あるいは、単独の受動的 OPEN 呼び出しによる LISTEN 状態のコネクションの "クローズ" を許してもよい。

4.2.2.19 生存時間: RFC-793 セクション 3.9, ページ 52

RFC793 は、TCP が TTL=60 で TCP セグメントを送信することを IP 層に要求すべきであると規定した。これは廃止され、TCP セグメントの送信で使用される TTL 値は設定可能でなければならない (MUST)。この議論については、セクション 3.2.1.7 を参照されたい。

4.2.2.20 イベント処理: RFC-793 セクション 3.9

厳密な要件ではないが、TCP は順序の異なる TCP セグメントをキューイング可能であるべきである (SHOULD)。70 ページの第一パラグラフの最後のセンテンスの "may" を "should" に変更する。

DISCUSSION:
幾つかの小規模なホスト実装は、バッファ空間が制限されているためにセグメントのキューイングを省略した。この省略は、単一セグメントの消失により以降のセグメント全てが "順序の異なって" 現れるため、TCP のスループットに有害な影響を及ぼすかもしれない。

通常、受信したセグメントの処理として、可能なときは必ず ACK セグメントを統合するよう実装しなければならない (MUST)。例えば、 もし TCP が一連のキューイングされたセグメントを処理しているならば、ACK セグメントを送信する前に全て処理しなければならない (MUST)。

以下に、RFC793 のイベント処理セクションに関する誤りの訂正と注意事項について詳述する。

  1. CLOSE 呼び出し、CLOSE-WAIT 状態、ページ 61。CLOSING ではなく LAST-ACK 状態に遷移する。

  2. LISTEN 状態、SYN のチェック (ページ 65, 66)。もしセグメントのセキュリティ/コンパートメントか優先度が誤っていたら、リセットを送信する。そのテキスト中のリセットの形式が誤っている。以下とすべき。

      <SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>

  3. SYN-SENT 状態、SYN のチェック、ページ 68。コネクションが ESTABLISHED 状態に遷移する時、以下の変数を設定しなければならない。

      SND.WND <- SEG.WND
      SND.WL1 <- SEG.SEQ
      SND.WL2 <- SEG.ACK

  4. セキュリティと優先度のチェック、ページ 71。最初の標題 "ESTABLISHED 状態" は、実際は SYN-RECEIVED 以外の全ての状態の一覧: ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT であるべきである。

  5. SYN ビットのチェック、ページ 71。"SYN-RECEIVED 状態で、もしコネクションが受動的 OPEN で起動されていれば、このコネクションを LISTEN 状態に戻してリターンする。さもなくば..."。

  6. ACK フィールドのチェック、SYN-RECEIVED 状態、ページ 72。コネクションが ESTABLISHED 状態に遷移する時に、(c) でリスト化された変数を設定しなければならない。

  7. ACK フィールドのチェック、ESTABLISHED 状態、ページ 72。もし SEG.ACK =< SND.UNA ならば、ACK が重複している (= が省略されていた)。同様に、SND.UNA =< SEG.ACK =< SND.NXT ならば、ウィンドウを更新すべきである。

  8. ユーザタイムアウト、ページ 77。

    TCP にコネクションを強制クローズさせずに、タイムアウトをアプリケーションに通知する方がよい。しかし、セクション 4.2.3.5 も参照されたい。

4.2.2.21 キューイングされたセグメントに対する肯定応答: RFC-793 セクション 3.9

TCP は、ウィンドウ内にあるがウィンドウの左端ではない正しいセグメントが到着したときに、RCV.NXT を 確認する ACK セグメントを送信してもよい (MAY)。

DISCUSSION:
RFC-793 (ページ 74 参照) は、順序通りでないセグメントを受信した時、すなわち、SEG.SEQ が RCV.NXT に等しくなかった時に、ACK セグメントを送信すべきか否かについて曖昧であった。

順序通りでないセグメントに対して ACK を送信する理由の一つは、"高速再送" として知られている実験的なアルゴリズムをサポートするためである。このアルゴリズムでは、再送タイマが満了する前にセグメントが消失したことを推理するために、送信側が "冗長な" ACK を使用する。

送信側は、同じ SEG.ACK の値を持ち、同じウィンドウの右端を持つ ACK を受信した回数を数える。もし、そのような ACK をしきい値を超えた回数分受信したら、SEG.ACK から始まるオクテットを含むセグメントが消失したものと仮定して、タイムアウトを待たずに再送する。しきい値はセグメントを並び替える見込みの、インターネットにおける最大を補償して選択される。高速再送アルゴリズムについては、どの程度有効であるかを決定するだけの十分な経験はまだ無い。

4.2.3 特定の問題

4.2.3.1 再送タイムアウトの計算

ホスト TCP は再送タイムアウトを ("RTO")を計算するために、Karn のアルゴリズムと Jacobson のアルゴリズムを実装しなければならない (MUST)。

実装体は同じセグメントの継続的な RTO 値に対して、"指数的なバックオフ" も含まなければならない (MUST)。SYN セグメントの再送は、データセグメントと同じアルゴリズムを使用すべきである (SHOULD)。

DISCUSSION:
RFC793 で規定された RTO の計算方法には、二つの既知の問題があった。第一に、再送があった時に正確な RTT の計測が困難なことである。第二に、なだらかなラウンドトリップ時間を算出するためのアルゴリズムが適切でないことである [TCP:7]。なぜならは、RTT 値の変動が小さく、一定であるという仮定は誤りだからである。これらの問題は、それぞれ Karn と Jacobson のアルゴリズムによって解決された。

これらの改善を使用することによるパフォーマンスの増加は、顕著に劇的に変化する。RTT の変化量の計測を組み込むための Jacobson のアルゴリズムは、通常のパケット長の変化が RTT のバリエーションを大きくするような低速回線上では特に重要である。あるベンダは、Jacobson の変動アルゴリズムを実装することによって、9.6kb の回線上の回線使用率が 10% から 90% に向上したことを見出している。

新しいコネクションで見積りパラメタを利用するために、以下の値を使用すべきである (SHOULD)。

  1. RTT = 0 秒。

  2. RTO = 3 秒。(なだらかな変化量は、この RTO に結果的に到る値に初期化される)。

推奨される RTO の上限値と下限値が、大規模なインターネットでは不適切であることが知られている。下限値は (高速 LAN に適応させるために) 秒の数分の一で計測すべきであり、上限値は 2*MSL、すなわち 240 秒にすべきである。

DISCUSSION:
経験上、これらの初期値が効率的であり、ともかく Karn と Jacobson のアルゴリズムは、TCP の振舞いを初期パラメタの選択に効率的に無反応にすることが分かっている。

4.2.3.2 いつ ACK セグメントを送信するか

TCP データセグメントのストリームを受信しているホストは、受信するデータセグメントにつき、1 つ以下の ACL (肯定応答) セグメントを送信することによって、インターネットとホストの両方の効率を増すことができる。これは "遅延 ACK" [TCP:5] として知られている。

TCP は遅延 ACK を実装すべきである (SHOULD) が、ACK を過度に遅らせるべきではない。遅延は 0.5 秒以下でなければならず (MUST)、フルサイズのセグメントの場合は、少なくとも毎秒セグメントに対して ACK が存在すべきである (SHOULD)。

DISCUSSION:
遅延 ACK はアプリケーションに、ウィンドウを更新し、おそらく即座に応答を送信する機会を与える。特にキャラクタモードのリモートログインの場合、遅延 ACK によって、サーバによって送信されるセグメントの個数が 3 の約数 (ACK, ウィンドウ更新、エコー文字が全て 1 つのセグメントに結合される) だけ減らすことができる。

さらに、ある大規模な複数ユーザのホストでは、遅延 ACK は実質的に、処理されるパケットの総個数を減らすことによって、プロトコル処理のオーバヘッドを減らすことができる [TCP:5]。しかし、ACK の過度の遅延は、ラウンドトリップのタイミングとパケット "クロッキング" アルゴリズム [TCP:7] の邪魔をする可能性がある。

4.2.3.3 いつウィンドウを更新するか

受信側の TCP は、SWS 回避アルゴリズムを含まなければならない (MUST)。[TCP:5]

IMPLEMENTATION:
受信側の SWS 回避アルゴリズムは、ウィンドウの右端をいつ進めてもよいかを決定する。これは慣例で "ウィンドウ更新" として知られている。現在のウィンドウを含んでいる ACK セグメントを、いつ実際に受信側に送信するかを決定するためには、このアルゴリズムと遅延 ACK アルゴリズム (セクション 4.2.3.2 参照) を組み合わせる。ここでは、RFC793 の表記方法を使用する。そのドキュメントの図 4 と図 5 を参照されたい。

受信側 SWS のソリューションは、たとえデータを小さいセグメントでネットワークから受信しても、ウィンドウの右端 RCV.NXT+RCV.WND を少しの増加で更新することを避けることである。

受信バッファ空間の総量が RCV.BUFF であると仮定する。ある時点でのこの総量の RCV.USER オクテットは、受信され確認されたデータと結びついているが、ユーザプロセスがまだ消費していない。コネクションが活動していなければ、RCV.NXT = RCV.BUFF であり、RCV.USER = 0 である。

データが到着して確認された時に、ウィンドウの右端を固定化する場合、バッファ空間全体よりも小さい値を申し出る必要がある。すなわち、受信側は RCV.NXT が増える時に、RCV.NXT+RCV.WND を一定に保つ RCV.WND を示さなければならない。従って、バッファ空間全体の RCV.BUFF は、通常三つの部分に分割される。


      |<------- RCV.BUFF ---------------->|
           1             2            3
  ----|---------|------------------|------|----
             RCV.NXT               ^
                                (Fixed)

  1 - RCV.USER =  受信したが、まだ消費されていないデータ
  2 - RCV.WND =   送信側に通知される空間
  3 - Reduction = 利用可能だが、まだ通知されていない空間

提案された受信側のための SWS 回避アルゴリズムは、Reduction が満たされるまで RCV.NXT+RCV.WND を固定に保つことである。

  RCV.BUFF - RCV.USER - RCV.WND  >= min( Fr * RCV.BUFF, Eff.snd.MSS )

Fr は推奨値が 1/2 である分数であり、Eff.snd.MSS はそのコネクションの有効送信 MSS である (セクション 4.2.2.6 参照)。この不等式を満たす場合、RCV.WND は RCV.BUFF-RCV.USER に設定される。

このアルゴリズムの一般的な効果は、RCV.WND を Eff.snd.MSS 単位で増やして進めることであることに注意されたい (現実的な受信バッファ: Eff.snd.MSS < RCV.BUFF/2)。受信側は Eff.snd.MSS が送信側のそれと同じ値であると仮定して、自分自身の Eff.snd.MSS を使用しなければならないことにも注意されたい。

4.2.3.4 いつデータを送信するか

送信側の TCP は、SWS 回避アルゴリズムを含まなければならない (MUST)。

TCP は短いセグメントをまとめるために、Nagle アルゴリズム [TCP:9] を実装すべきである (SHOULD)。しかし、アプリケーションが個々のコネクションにおいて、Nagle アルゴリズムを不可にする方法が存在しなければならない (MUST)。あらゆるケースにおいて、送信するデータはスロースタートアルゴリズム (セクション 4.2.2.15) によって課せられる制限も受ける。

DISCUSSION:
Nagle アルゴリズムは、一般に次の通り。

  もし未確認のデータがあれば (すなわち SND.NXT > SND.UNA)、未確認 
  のデータが確認されるか、TCP がフルサイズのセグメント 
  (Eff.snd.MSS バイト、セクション 4.2.2.6 を参照されたい) を送信で
  きるまで、送信側 TCP は全てのユーザデータをバッファリングする。

幾つかのアプリケーションは (例えばリアルタイムの表示ウィンドウ更新)、Nagle アルゴリズムを使用しない必要がある。それにより、小さいデータグラムセグメントを最大の割合で送出することができる。

IMPLEMENTATION:
送信側の SWS 回避アルゴリズムは受信側のよりも難しい。なぜなら、送信側は受信側のバッファ空間の総量 RCV.BUFF を (直接的には) 知らないからである。うまく動作させるために発見されたアプローチは、送信側が Max(SND.WND)、コネクション上でそれまで見られた最大送信ウィンドウを算出して、RCV.BUFF の概算としてこの値を使用することである。不幸にもこれはあくまで概算であり、受信側は如何なる時でも RCV.BUFF のサイズを減らすことができる。デッドロックを結果として招くことを避けるために、SWS 回避アルゴリズムを無効にして、データの送信を強制するためのタイムアウトを持つ必要がある。実際は、このタイムアウトは滅多に発生しないはずである。

"使用可能なウィンドウ" [TCP:5] は:

  U = SND.UNA + SND.WND - SND.NXT

すなわち、申し出されたウィンドウから、送信したが確認されていないデータの総量を引いたものである。もし D が送信側 TCP でキューイングされているが、まだ送信されていないデータの総量ならば、以下の規則のセットが推奨される。

以下の条件に合致したらデータを送信する:

  1. もし最大サイズのセグメントが送信できるならば、すなわち以下ならば

      min(D,U) >= Eff.snd.MSS;

  2. あるいは、もしデータがプッシュされ、全てのキューイングされたデータが今送信できるならば、すなわち以下ならば

      [SND.NXT = SND.UNA and] PUSHED and D <= U

    (角括弧内の条件は Nagle アルゴリズムによって課せられる)

  3. あるいは、もし少なくとも最大ウィンドウの分数 Fs が送信できるならば、すなわち以下ならば

      [SND.NXT = SND.UNA and] min(D.U) >= Fs * Max(SND.WND);

  4. あるいは、もしデータが PUSH され、無効タイムアウトが発生したら

この Fs は、推奨された値が 1/2 の分数である。無効タイムアウトは 0.1〜1.0 秒の範囲であるはずである。このタイマを、ゼロウィンドウのプローブ (セクション 4.2.2.17) で使用されるタイマと一緒にすると便利かもしれない。

最後に、正に規定された SWS 回避アルゴリズムは、[TCP:5] に含まれている送信側アルゴリズムの代わりに使用されることに注意されたい。

4.2.3.5 TCP コネクション障害

TCP による同じセグメントの過渡の再送は、リモートホストかインターネットパスの何らかの障害を示す。この障害は短期間かもしれないし、長期間かもしれない。過度のデータセグメントの再送を取り扱うために、以下の手続きを使用しなければならない (MUST)。[IP:11]

  1. 同じセグメントに対して発生した再送の個数を計測する、R1 と R2 の二つのしきい値が存在する。R1 と R2 は時間単位か、再送数で計測されるかもしれない。

  2. 同じセグメントの送信回数がしきい値 R1 に達するか超えた場合、死んだゲートウェイの診断を行わせるために否定的なアドバイスを IP 層に渡す (セクション 3.3.1.4 参照)。

  3. 同じセグメントの送信回数がしきい値 R1 よりも大きい R2 に達するか超えた場合、コネクションをクローズする。

  4. アプリケーションは、特定のコネクションに対して、R2 の値を設定できなければならない (MUST)。例えば、対話的アプリケーションは R2 を "無限" に設定してもよく、切断するタイミングをユーザに制御させられる。

  5. R2 の前に R1 に達したら、TCP はアプリケーションに配送の問題を通知すべきである (SHOULD)。(もしそのような情報がアプリケーションによって利用不能でないならば。セクション 4.2.4.1 参照)。これによって、例えばリモートログイン (ユーザ Telnet) アプリケーションプログラムが、ユーザに知らせることができる。

R1 の値は、少なくとも現在の RTO で、3 回の再送に相当すべきである (SHOULD)。R2 の値は少なくとも 100 秒に相当すべきである (SHOULD)。

TCP コネクションをオープンする試みは、SYN セグメンの過度の再送か RST セグメントの受信、ICMP ポート未到達で失敗する可能性がある。SYN 再送は、アプリケーション層に通知することを含め、データの再送で規定されている一般的な方法で処理しなければならない (MUST)。

しかし、R1 と R2 の値は SYN とデータセグメントでは異なってもよい。特に SYN セグメントに対する R2 は、少なくとも 3 分間、セグメントの再送を提供できるほど、十分大きな値を設定しなければならない (MUST)。無論アプリケーションは、より早くコネクションをクローズする (例えばオープンの試みを諦める) ことができる。

DISCUSSION:
幾つかのインターネットパスはかなりの設定時間を要し、そうしたパスの数は将来増えると思われる。

4.2.3.6 TCP Keep-Alives

この実行は一般には受け入れられていないが、実装者は TCP の実装体に "keep-alive" を含めてもよい (MAY)。もし keep-alive が含まれるならば、アプリケーションは各々の TCP コネクションに対して、その使用/未使用を指定できなければならず (MUST)、デフォルトは未使用でなければならない (MUST)。

keep-alive パケットは、ある間隔内にコネクションでデータや肯定応答パケットを受信しない時にのみ送信しなければならない (MUST)。その間隔は設定可能でなければならず (MUST)、デフォルトは 2時間以上でなければならない (MUST)。

データを含んでいない ACK セグメントは、TCP によって信頼できる送信がされていないことを覚えておくことは、極めて重要である。もし keep-alive メカニズムを実装する場合、ある特定のプローブに対して応答が無いことを、コネクションが死んだものと解釈してはならない (MUST NOT)。

実装体は、データが付かない keep-alive セグメントを送信すべきである (SHOULD)。しかし、誤った TCP 実装体との互換性のために、一つのごみオクテットを含んだ keep-alive セグメントを送信するよう、設定可能であってもよい (MAY)。

DISCUSSION:
"keep-alive" メカニズムは、コネクションがさもなくばアイドルである時に、送信すべきデータが無くても、コネクションのもう一方の終端を定期的にプローブする。TCP の規定は keep-alive メカニズムを含んでいない。なぜならば、(1) 一時的なインターネット障害の間に、完全に有効なコネクションを切断する可能性がある。(2) 不要な帯域を消費する。("もし誰もそのコネクションを使っていなければ、それが有効であるか否かなど誰が気にするだろうか")。(3) パケット課金のインターネットパスでお金がかかる。

しかしながら、幾つかの TCP 実装は、keep-alive メカニズムを含めている。アイドルコネクションがまだ活性であることを確認するために、これらの実装体は相手の TCP から応答を引き出すことを意図したプローブセグメントを送信する。そのセグメントは通常 SEG.SEQ = SND.NXT-1 を含み、ごみデータを 1 オクテット含んでも含まなくてもよい。平穏なコネクションは SND.NXT = RCV.NXT である。よって、この SEG.SEQ はウィンドウの範囲外である。従って、このプローブによって受信側は肯定応答セグメントを返却することになり、コネクションがまだ活性であることが確認できる。もし相手が、ネットワークの分断やクラッシュによってそのコネクションを落としていたら、相手は肯定応答セグメントではなく RST で応答するだろう。

不幸にも、幾つかの誤って動作する TCP 実装体は、セグメントがデータを含んでいなければ、SEG.SEQ = SND.NXT-1 を持つセグメントに対して応答しない。代替手段として実装体は、相手がごみデータオクテットを付けない keep-alive パケットに対して、正しく応答したか否かを決めることができる。

TCP keep-alive メカニズムは、もしクライアントがネットワーク障害の間にクラッシュするかコネクションをアボートしたら、いつまでもハングしてリソースを不必要に消費するサーバアプリケーションでのみ発行すべきである。

4.2.3.7 TCP マルチホーム

マルチホーム化さけたホスト上のアプリケーションが、積極的に TCP コネクションをオープンする時にローカル IP アドレスを指定しないならば、TCP は (一番最初の) SYN を送信する前に、ローカル IP アドレスの選択を IP 層に依頼しなければならない (MUST)。セクション 3.4 の GET_SRCADDR() 関数を参照されたい。

それ以外の時は、このコネクション上で前のセグメントが送信あるいは受信されており、TCP は直前のセグメントで使われていたものと同じローカルアドレスを使用しなければならない (MUST)。

4.2.3.8 IP オプション

受信したオプションが IP 層から TCP に渡される時、TCP は理解できないオプションを無視しなければならない (MUST)。

TCP はタイムスタンプと経路記録オプションをサポートしてもよい (MAY)。

アプリケーションは積極的に TCP コネクションをオープンする時に、送信元経路オプションを指定できなければならない (MUST)。そしてこれは、データグラムで受信した送信元経路よりも優先しなければならない (MUST)。

TCP コネクションを受動的に OPEN して、完全な IP 送信元経路オプション (返却経路を含む) 付きのパケットが到着した時、TCP は返却経路を保存して、このコネクションに送信するセグメントでそれを使用しなければならない (MUST)。もし以降のセグメントで異なる送信元経路が到着したら、後者の定義が前者を上書きすべきである (SHOULD)。

4.2.3.9 ICMP メッセージ

TCP は IP 層から渡される ICMP エラーメッセージに基づいて、エラーを生成したコネクションに向けて動作しなければならない (MUST)。必要な合流化情報は、ICMP メッセージ内に含まれる IP ヘッダの中で見つけることができる。

・送信元消失

TCP は、そのコネクションへの送信を送らせることによって、送信元消失に反応しなければならない (MUST)。送信元消失に対して推奨される (RECOMMENDED) 手続きは、あたかも再送タイムアウトが発生したかのように "スロースタート" を実行することである。

・宛先未到達 -- コード 0, 1, 5

これらの宛先未到達メッセージはソフト異常の状態を示しているので、TCP はそのコネクションをアボートしてはならず (MUST NOT)、その情報をアプリケーションで利用可能とすべきである (SHOULD)。

DISCUSSION:
TCP はソフト異常の状態を ERROR_REPORT ルーチンの上位呼び出しで、アプリケーション層に直接通知することができる。さもなくば TCP コネクションがタイムアウトしなければ、そのメッセージを表してアプリケーションに通知することがほとんどできない。

・宛先未到達 -- コード 2-4

これらはハード異常の状態である。よって、TCP はそのコネクションをアボートすべきである (SHOULD)。

・時間超過 -- コード 0, 1

これは、宛先未到達のコード 0, 1, 5 と同じ方法で扱うべきである (上記参照)。

・パラメメタ問題

これは、宛先未到達のコード 0, 1, 5 と同じ方法で扱うべきである (上記参照)。

4.2.3.10 リモートアドレス検証

TCP 実装体は、不正なリモート IP アドレス (例えばブロードキャストやマルチキャストアドレス等) に対して、ローカル OPEN 呼び出しのエラーとして拒否しなければならない (MUST)。

不正な送信元アドレスを持つ入力 SYN は、TCP か IP 層のいずれかによって無視しなければならない (MUST) (セクション 3.2.1.3 参照)。

TCP 実装は、ブロードキャストかマルチキャストアドレスに宛てられた入力 SYN セグメントを、黙って破棄しなければならない (MUST)。

4.2.3.11 TCP トラフィックパターン

IMPLEMENTATION:
TCP プロトコル規定 [TCP:1] は、コネクション上のメッセージフローを制御するアルゴリズム、パケット化やウィンドウの管理、肯定応答の送信等を設計する際の自由度を実装者に与えている。TCP は幅広いトラフィックパターンに適応しなければならないので、これらの設計の決定は難しい。経験上 TCP 実装者は、以下の二つの極端なトラフィックパターンについての設計を確かめる必要があることが判明している。

更に経験上では、単一の TCP は効果的かつ効率的に、これら二つの極端なケースを扱えることが判っている。

新しい TCP 実装を検査するための最も重要なツールは、パケットトレースプログラムである。他の TCP 実装との様々なトラフィックパターンをトレースし、その結果を注意深く検証する重要性は、非常に数多くの経験が物語っている。

4.2.3.12 効率性

IMPLEMENTATION:
幅広い経験則より、効率的な TCP の実装に対して以下の提案が導き出される。

  1. データをコピーしてはならない

    大容量データ転送では、CPU に集中する主要なタスクは、ある場所から別の場所にデータをコピーして、データのチェックサムを計算することである。TCP データのコピー回数を最小化することは非常に重要である。根本的なスピードの制限は、メモリバスを通じてデータをフェッチすることかもしれないので、コピーとチェックサム計算を併用し、一回のメモリフェッチで両方を実行することは効果的かもしれない。

  2. ハードウェア組込みチェックサム計算ルーチン

    優れた TCP チェックサム計算ルーチンは、単純で定義そのままの実装よりも 2 倍から 5 倍速い。多大な注意と賢いコーディングはしばしば必要であり、チェックサムを計算するコードを "強烈に高速" にすることが望ましい。[TCP:10] 参照

  3. 最も一般的なケースのコード

    TCP プロトコル処理は複雑であるが、大半のセグメントについては、ほんのわずかで簡単な決定を行えばよい。最も一般的なケースで決定する回数を最小化するよう、主要な行をコーディングすることによって、セグメント毎の処理は非常にスピードアップするだろう。

4.2.4 TCP/アプリケーション層インタフェース

4.2.4.1 非同期通知

軽度な TCP エラー状態をアプリケーションに通知するメカニズムが存在しなければならない (MUST)。これは一般に、トランスポート層から非同期に上位呼び出しされる [INTRO:7]、アプリケーション提供の ERROR_REPORT ルーチンを想定している。

  ERROR_REPORT(local connection name, reason, subreason)

reason と subreason パラメタの正確な符号化についてはここでは既定しない。しかし、非同期にアプリケーションに以下を通知するという条件は含まなければならない (MUST)。

しかし、ERROR_REPORT 呼び出しを受けたくないアプリケーションプログラムは、効果的にこれらの呼び出しを無効にできるべきである (SHOULD)。

DISCUSSION:
これらのエラー通知は通常、多くのアプリケーションによって害なく無視できるソフトエラーを反映している。これらのエラー通知呼び出しは、デフォルトでは "無効" にすべきであると提案されているが、これは要件ではない。

4.2.4.2 サービスタイプ

アプリケーション層は、コネクション上で送信されるセグメントにサービスタイプ (TOS) を指定できなければならない (MUST)。要件ではないが、アプリケーションはコネクションが生存中は TOS を変更できるべきである (SHOULD)。TCP はコネクション上にセグメントを送信する時、現在の TOS 値を変更せずに IP 層に渡すべきである (SHOULD)。

TOS はコネクションの各方向毎に独立して指定されるので、受信側アプリケーションは ACK セグメントで使用する TOS を指定するだろう。

TCP は最も最近受信した TOS をアプリケーションに渡してもよい (MAY)。

DISCUSSION:
幾つかのアプリケーション (例えば SMTP) は、コネクションが生存中に通信の性質を変更するので、TOS の指定を変更したいかもしれない。

RFC793 で既定された OPEN 呼び出しもまた、呼び出し側が送信元経路や経路記録やタイムスタンプなどの IP オプションを指定できるパラメタ ("オプション") を含んでいることに注意されたい。

4.2.4.3 フラッシュ呼び出し

幾つかの TCP 実装は FLUSH 呼び出しを含んでいる。それは、ユーザが SEND 呼び出しを発行したが、まだ現在の送信ウィンドウの右にあり、TCP の送信キューに溜まっているデータを空にする。すなわち、シーケンス番号の同期を失わず、可能な限りのキューイングされている送信データをフラッシュする。これは、telnet の "アボート出力" 機能で効果的である。

4.2.4.4 マルチホーム化

RFC793 のセクション 2.7 と 3.8 で概説されているユーザインタフェースは、マルチホーム化のために拡張する必要がある。OPEN 呼び出しはローカル IP アドレスの指定を可能にするために、以下の任意のパラメタを持たなければならない (MUST)。

  OPEN( ... [local IP address,] ... )

DISCUSSION:
幾つかの TCP ベースのアプリケーションは、ある特定のコネクションを使用するためのローカル IP アドレスを指定する必要がある。例えば FTP がそれに該当する。

IMPLEMENTATION:
"ローカル IP アドレス" パラメタが指定された受動的 OPEN 呼び出しは、そのアドレス向けのコネクション要求の受信を待つ。もしそのパラメタが未指定ならば、受動的 OPEN は全てのローカル IP アドレス向けのコネクション要求の受信を待ち、使用されている特定のアドレスへのコネクションのローカル IP アドレスをバインドする。

能動的 OPEN 呼出しでは、指定された "ローカル IP アドレス" パラメタは、コネクションをオープンするために使用される。もしそのパラメタが未指定ならば、ネットワークソフトウェアは、そのコネクションに対する適切なローカル IP アドレスを選択するだろう (セクション 3.3.4.2 参照)。

4.2.5 TCP 要件要約

                                                 |        | | | |S| |
                                                 |        | | | |H| |F
                                                 |        | | | |O|M|o
                                                 |        | |S| |U|U|o
                                                 |        | |H| |L|S|t
                                                 |        |M|O| |D|T|n
                                                 |        |U|U|M| | |o
                                                 |        |S|L|A|N|N|t
                                                 |        |T|D|Y|O|O|t
FEATURE                                          |SECTION | | | |T|T|e
-------------------------------------------------|--------|-|-|-|-|-|--
                                                 |        | | | | | |
プッシュフラグ                                   |        | | | | | |
  プッシュ無しデータを集める/キューイングする    |4.2.2.2 | | |x| | |
  送信側は継続する PSH フラグを破棄する          |4.2.2.2 | |x| | | |
  SEND 呼び出しが PUSH を指定可能                |4.2.2.2 | | |x| | |
    もし不可: 送信側がいつまでもバッファに溜める |4.2.2.2 | | | | |x|
    もし不可: 最後のセグメントに PSH 指定        |4.2.2.2 |x| | | | |
  受信側 ALP に PSH を通知する                   |4.2.2.2 | | |x| | |1
  可能な場合、最大長のセグメントを送信する       |4.2.2.2 | |x| | | |
                                                 |        | | | | | |
ウィンドウ                                       |        | | | | | |
  符号無し整数として扱う                         |4.2.2.3 |x| | | | |
  32 ビット値として扱う                          |4.2.2.3 | |x| | | |
  右側からウィンドウを縮小する                   |4.2.2.16| | | |x| |
  ウィンドウ縮小に対して頑強である               |4.2.2.16|x| | | | |
  受信側のウィンドウをずっと閉じたままにする     |4.2.2.17| | |x| | |
  送信側がゼロウィンドウをプローブする           |4.2.2.17|x| | | | |
    RTO 後の一番最初にプローブする               |4.2.2.17| |x| | | |
    指数的なバックオフ                           |4.2.2.17| |x| | | |
  ウィンドウがずっとゼロに留まることを許可する   |4.2.2.17|x| | | | |
  ゼロウィンドウで送信側が OK conn をタイムアウト|4.2.2.17| | | | |x|
                                                 |        | | | | | |
緊急データ                                       |        | | | | | |
  ポインタは最終オクテットを指す                 |4.2.2.4 |x| | | | |
  緊急データシーケンスの長さが任意であること     |4.2.2.4 |x| | | | |
  緊急データを非同期に ALP に通知する            |4.2.2.4 |x| | | | |1
  ALP がどのくらい緊急データがキューにあるか知る |4.2.2.4 |x| | | | |1
                                                 |        | | | | | |
TCP オプション                                   |        | | | | | |
  如何なるセグメント中の TCP オプションも受信    |4.2.2.5 |x| | | | |
  未サポートのオプションを無視する               |4.2.2.5 |x| | | | |
  不正なオプション長に対処する                   |4.2.2.5 |x| | | | |
  MSS オプションの送信と受信を実装する           |4.2.2.6 |x| | | | |
  536 でなければ MSS オプションを送信する        |4.2.2.6 | |x| | | |
  常に MSS オプションを送信する                  |4.2.2.6 | | |x| | |
  送信 MSS のデフォルトが 536 である             |4.2.2.6 |x| | | | |
  有効送信セグメント長を算出する                 |4.2.2.6 |x| | | | |
                                                 |        | | | | | |
TCP チェックサム                                 |        | | | | | |
  送信側がチェックサムを計算する                 |4.2.2.7 |x| | | | |
  受信側がチェックサムをチェックする             |4.2.2.7 |x| | | | |
                                                 |        | | | | | |
クロック駆動の初期シーケンス選択を使用する       |4.2.2.9 |x| | | | |
                                                 |        | | | | | |
コネクションのオープン                           |        | | | | | |
  同時オープンの試みをサポートする               |4.2.2.10|x| | | | |
  SYN-RCVD に達するときに最後の状態を覚えている  |4.2.2.11|x| | | | |
  受動的オープン呼び出しが他の呼び出しを妨げる   |4.2.2.18| | | | |x|
  同じポートを同時に LISTEN する機能             |4.2.2.18|x| | | | |
  必要なら SYN の送信元アドレスを IP に尋ねる    |4.2.3.7 |x| | | | |
    さもなくば conn のローカルアドレスを使用     |4.2.3.7 |x| | | | |
  bcast/mcast IP アドレス向けにオープンする      |4.2.3.14| | | | |x|
  bcast/mcast アドレスへのセグメントを黙って破棄 |4.2.3.14|x| | | | |
                                                 |        | | | | | |
コネクションのクローズ                           |        | | | | | |
  RST がデータを含む                             |4.2.2.12| |x| | | |
  コネクションのアポートをアプリケーションに通知 |4.2.2.13|x| | | | |
  コネクションの半二重クローズ                   |4.2.2.13| | |x| | |
    データ消失を示すために RST 送信              |4.2.2.13| |x| | | |
  2×MSL 秒間 TIME-WAIT 状態にいる               |4.2.2.13|x| | | | |
    TIME-WAIT 状態から SYN を受け入れる          |4.2.2.13| | |x| | |
                                                 |        | | | | | |
再送                                             |        | | | | | |
  Jacobson スロースタートアルゴリズム            |4.2.2.15|x| | | | |
  Jacobson 輻輳回避アルゴリズム                  |4.2.2.15|x| | | | |
  同じ IP 識別子で再送する                       |4.2.2.15| | |x| | |
  Karn のアルゴリズム                            |4.2.3.1 |x| | | | |
  Jacobson の RTO 見積りアルゴリズム             |4.2.3.1 |x| | | | |
  指数的なバックオフ                             |4.2.3.1 |x| | | | |
  SYN の RTO はデータと同様に計算する            |4.2.3.1 | |x| | | |
  推奨された初期値と範囲を使用する               |4.2.3.1 | |x| | | |
                                                 |        | | | | | |
ACK 生成:                                        |        | | | | | |
  順序の異なるセグメントをキューイングする       |4.2.2.20| |x| | | |
  ACK を送信する前にキューを全て処理する         |4.2.2.20|x| | | | |
  順序の異なるセグメントに対して ACK 送信        |4.2.2.21| | |x| | |
  遅延 ACK                                       |4.2.3.2 | |x| | | |
    遅延時間 < 0.5 秒                            |4.2.3.2 |x| | | | |
    2つめのフルサイズセグメントに対して ACK      |4.2.3.2 |x| | | | |
  受信側で SWS 回避アルゴリズム                  |4.2.3.3 |x| | | | |
                                                 |        | | | | | |
データ送信                                       |        | | | | | |
  TTL が設定可能                                 |4.2.2.19|x| | | | |
  送信側で SWS 回避アルゴリズム                  |4.2.3.4 |x| | | | |
  Nagle アルゴリズム                             |4.2.3.4 | |x| | | |
    APL が Nagle アルゴリズムを無効にできる      |4.2.3.4 |x| | | | |
                                                 |        | | | | | |
コネクション障害:                                |        | | | | | |
  R1 を超えたら IP に否定的なアドバイスを行う    |4.2.3.5 |x| | | | |
  R2 を超えたらコネクションをクローズする        |4.2.3.5 |x| | | | |
  ALP は R2 を設定可能                           |4.2.3.5 |x| | | | |1
  R1<= R2< になったら ALP に通知する             |4.2.3.5 | |x| | | |1
  R1, R2 の推奨値を使用する                      |4.2.3.5 | |x| | | |
  SYN と同じメカニズムとする                     |4.2.3.5 |x| | | | |
    SYN の場合 R2 は少なくとも 3 分              |4.2.3.5 |x| | | | |
                                                 |        | | | | | |
Keep-alive パケットの送信:                       |4.2.3.6 | | |x| | |
  - アプリケーションが要求できる                 |4.2.3.6 |x| | | | |
  - デフォルトは "未使用" である                 |4.2.3.6 |x| | | | |
  - ある間隔の間アイドルの場合にのみ送信する     |4.2.3.6 |x| | | | |
  - 間隔を設定可能                               |4.2.3.6 |x| | | | |
  - デフォルトは少なくとも 2 時間                |4.2.3.6 |x| | | | |
  - ACK の消失に耐えられる                       |4.2.3.6 |x| | | | |
                                                 |        | | | | | |
IP オプション                                    |        | | | | | |
  TCP が理解できないオプションを無視する         |4.2.3.8 |x| | | | |
  タイムスタンプをサポートする                   |4.2.3.8 | | |x| | |
  経路記録をサポートする                         |4.2.3.8 | | |x| | |
  送信元経路:                                    |        | | | | | |
    ALP が指定可能である                         |4.2.3.8 |x| | | | |1
      データグラム中の送信元経路を上書きする     |4.2.3.8 |x| | | | |
    送信元経路から返却経路を生成する             |4.2.3.8 |x| | | | |
    以前の送信元経路を上書きする                 |4.2.3.8 | |x| | | |
                                                 |        | | | | | |
IP から ICMP メッセージを受信する                |4.2.3.9 |x| | | | |
  宛先未到達 (0,1,5) -> アプリケーションに通知   |4.2.3.9 | |x| | | |
  宛先未到達 (0,1,5) -> コネクションをアボート   |4.2.3.9 | | | | |x|
  宛先未到達 (2-4) ->コネクションをアポート      |4.2.3.9 | |x| | | |
  送信元消失 => スロースタート                   |4.2.3.9 | |x| | | |
  時間超過 => アプリに通知、アボートしない       |4.2.3.9 | |x| | | |
  パラメタ問題 => アプリに通知、アボートしない   |4.2.3.9 | |x| | | |
                                                 |        | | | | | |
アドレス違反                                     |        | | | | | |
  不正な IP アドレスへの OPEN 呼び出しを拒否する |4.2.3.10|x| | | | |
  不正な IP アドレスからの SYN を拒否する        |4.2.3.10|x| | | | |
  bcast/mcast アドレスへの SYN を黙って破棄する  |4.2.3.10|x| | | | |
                                                 |        | | | | | |
TCP/アプリケーションインタフェースサービス       |        | | | | | |
  エラー通知メカニズム                           |4.2.4.1 |x| | | | |
  APL がエラー通知ルーチンを無効にできる         |4.2.4.1 | |x| | | |
  APL が送信での TOS を指定できる                |4.2.4.2 |x| | | | |
    IP に変更無しで渡す                          |4.2.4.2 | |x| | | |
  APL がコネクションの間に TOS を変更できる      |4.2.4.2 | |x| | | |
  受信した TOS をアプリケーションに渡す          |4.2.4.2 | | |x| | |
  FLUSH 呼び出し                                 |4.2.4.3 | | |x| | |
  OPEN で任意のローカル IP アドレスパラメタ      |4.2.4.4 |x| | | | |
-------------------------------------------------|--------|-|-|-|-|-|--
-------------------------------------------------|--------|-|-|-|-|-|--

脚注:
  (1) "ALP" はアプリケーション層プログラムを意味する。

前へ    次へ    先頭へ