4. トランスポートプロトコル (TRANSPORT PROTOCOLS)
4.1 ユーザーデータグラムプロトコル -- UDP (USER DATAGRAM PROTOCOL)
4.1.1 はじめに (INTRODUCTION)
ユーザーデータグラムプロトコル (User Datagram Protocol, UDP) [UDP:1] は、最小限のトランスポートサービス(非保証データグラム配信)のみを提供し、アプリケーションにIP層のデータグラムサービスへの直接アクセスを提供します。UDPは、TCPのサービスレベルを必要としないアプリケーション、またはTCPで利用できない通信サービス(マルチキャストやブロードキャスト配信など)を使用したいアプリケーションによって使用されます。
UDPはほぼヌルプロトコルです。IPの上で提供する唯一のサービスは、データのチェックサムとポート番号による多重化です。したがって、UDP上で実行されるアプリケーションプログラムは、コネクション指向プロトコルが処理するエンドツーエンド通信の問題、例えば信頼性のある配信のための再送信、パケット化と再組み立て、フロー制御、輻輳回避などを、これらが必要な場合には直接処理する必要があります。IPとTCPの間のかなり複雑な結合は、UDPとUDPを使用する多くのアプリケーションの間の結合に反映されます。
4.1.2 プロトコルウォークスルー (PROTOCOL WALK-THROUGH)
UDPの仕様には既知のエラーはありません。
4.1.3 特定の問題 (SPECIFIC ISSUES)
4.1.3.1 ポート (Ports)
UDPのウェルノウンポートは、TCPのウェルノウンポートと同じルールに従います。以下の4.2.2.1節を参照してください。
保留中のLISTEN呼び出しがないUDPポートにアドレス指定されたデータグラムが到着した場合、UDP すべきである (SHOULD) はICMPポート到達不能メッセージを送信します。
4.1.3.2 IPオプション (IP Options)
UDP しなければならない (MUST) は、IP層から受信したすべてのIPオプションを透過的にアプリケーション層に渡します。
アプリケーション しなければならない (MUST) は、そのUDPデータグラムで送信するIPオプションを指定できる必要があり、UDP しなければならない (MUST) はこれらのオプションをIP層に渡します。
議論 (DISCUSSION):
現在、UDPを通過する必要がある唯一のオプションは、ソースルート (Source Route)、レコードルート (Record Route)、タイムスタンプ (Time Stamp) です。ただし、将来新しいオプションが定義される可能性があり、UDPはアプリケーションとの間で渡すオプションの形式や内容について仮定する必要はなく、またすべきではありません。IP層セキュリティオプションは例外である可能性があります。
UDPベースのアプリケーションは、リクエストデータグラムからソースルートを取得し、対応する応答を送信するための逆ルートを提供する必要があります。
4.1.3.3 ICMPメッセージ (ICMP Messages)
UDP しなければならない (MUST) は、IP層から受信したすべてのICMPエラーメッセージをアプリケーション層に渡します。少なくとも概念的には、これはERROR_REPORTルーチンへの上方呼び出し(4.2.4.1節を参照)で実現できます。
議論 (DISCUSSION):
UDPデータグラムの送信に起因するICMPエラーメッセージは非同期に受信されることに注意してください。ICMPエラーメッセージを受信したいUDPベースのアプリケーションは、これらのメッセージが到着したときに逆多重化するために必要な状態を維持する責任があります。例えば、アプリケーションはこの目的のために保留中の受信操作を保持する場合があります。アプリケーションはまた、同じポートの以前の使用による遅延ICMPエラーメッセージからの混乱を避ける責任があります。
4.1.3.4 UDPチェックサム (UDP Checksums)
ホスト しなければならない (MUST) は、UDPチェックサムを生成および検証する機能を実装します。アプリケーション してもよい (MAY) は、UDPチェックサムを生成するかどうかを任意で制御できますが、デフォルトではチェックサムを有効にする しなければならない (MUST) です。
ゼロでなく無効なチェックサムでUDPデータグラムが受信された場合、UDP しなければならない (MUST) はそのデータグラムを静かに破棄します。アプリケーション してもよい (MAY) は、チェックサムのないUDPデータグラムを破棄するかアプリケーションに渡すかを任意で制御できます。
議論 (DISCUSSION):
通常はローカルエリアネットワークでのみ実行される一部のアプリケーションは、効率のためにUDPチェックサムをオフにすることを選択します。その結果、多くの未検出エラーが報告されています。UDPチェックサムをオフにすべきかどうかについての推奨事項は非常に議論の余地があります。
実装 (IMPLEMENTATION):
UDPチェックサムには一般的な実装エラーがあります。TCPチェックサムとは異なり、UDPチェックサムはオプションです。UDPヘッダーチェックサムフィールドで転送されるゼロは、チェックサムがないことを示します。送信側が実際に計算したUDPチェックサムがゼロの場合、チェックサムを全1(65535)として送信する必要があります。受信側は特別なアクションを取る必要はありません。1の補数演算では、ゼロと65535は等価だからです。
4.1.3.5 UDPマルチホーミング (UDP Multihoming)
UDPデータグラムが受信されたとき、その特定の宛先アドレス しなければならない (MUST) はアプリケーション層に渡されます。
アプリケーション しなければならない (MUST) は、UDPデータグラムの送信に使用するIP送信元アドレスを指定できる必要があります。または空のままにすることもできます(この場合、ネットワークソフトウェアが適切な送信元アドレスを選択します)。選択した送信元アドレスをアプリケーション層に通知する方法が あるべきである (SHOULD) です(例えば、アプリケーションが後で対応するインターフェースからのみ応答データグラムを受信できるようにするため)。
議論 (DISCUSSION):
UDPを使用するリクエスト/レスポンスアプリケーションは、リクエストの特定の宛先アドレスと同じ送信元アドレスを使用して応答する必要があります。[INTRO:1]の「一般的な問題」セクションを参照してください。
4.1.3.6 無効なアドレス (Invalid Addresses)
無効なIP送信元アドレス(ブロードキャストまたはマルチキャストアドレスなど)で受信されたUDPデータグラム しなければならない (MUST) は、UDPまたはIP層によって破棄されます(3.2.1.3節を参照)。
ホストがUDPデータグラムを送信するとき、送信元アドレス しなければならない (MUST) はホストのIP(1つまたは複数の)アドレスの1つです。
4.1.4 UDP/アプリケーション層インターフェース (UDP/APPLICATION LAYER INTERFACE)
UDPのアプリケーションインターフェース しなければならない (MUST) は、このドキュメントの3.4節で説明されているIP/トランスポートインターフェースの完全なサービスを提供します。したがって、UDPを使用するアプリケーションは、3.4節で説明されているGET_SRCADDR()、GET_MAXSIZES()、ADVISE_DELIVPROB()、およびRECV_ICMP()関数を必要とします。例えば、GET_MAXSIZES()を使用して、特定の{インターフェース、リモートホスト、TOS}トリプレットの有効な最大UDPデータグラムサイズを知ることができます。
アプリケーション層プログラム しなければならない (MUST) は、UDPデータグラムを送信するためのTTLとTOS値、およびIPオプションを設定でき、これらの値はIP層に透過的に渡される必要があります。UDP してもよい (MAY) は、受信したTOSをアプリケーション層に渡します。
4.1.5 UDP要件サマリー (UDP REQUIREMENTS SUMMARY)
| 機能 | 章節 | 必須 (MUST) | すべき (SHOULD) | 可能 (MAY) | してはならない (MUST NOT) |
|---|---|---|---|---|---|
| UDP | |||||
| --- | --- | --- | --- | --- | --- |
| UDP送信ポート到達不能 | 4.1.3.1 | x | |||
| UDPでのIPオプション | |||||
| - 受信したIPオプションをアプリケーション層に渡す | 4.1.3.2 | x | |||
| - アプリケーション層が送信時にIPオプションを指定可能 | 4.1.3.2 | x | |||
| - UDPがIPオプションをIP層に渡す | 4.1.3.2 | x | |||
| ICMPメッセージをアプリケーション層に渡す | 4.1.3.3 | x | |||
| UDPチェックサム: | |||||
| - チェックサムを生成/検証する機能 | 4.1.3.4 | x | |||
| - 無効なチェックサムを静かに破棄 | 4.1.3.4 | x | |||
| - 送信側オプションでチェックサムを生成しない | 4.1.3.4 | x | |||
| - デフォルトでチェックサムを有効 | 4.1.3.4 | x | |||
| - 受信側オプションでチェックサムを要求 | 4.1.3.4 | x | |||
| UDPマルチホーミング | |||||
| - 特定の宛先アドレスをアプリケーション層に渡す | 4.1.3.5 | x | |||
| - アプリケーション層がローカルIPアドレスを指定可能 | 4.1.3.5 | x | |||
| - アプリケーション層がワイルドカードローカルIPアドレスを指定可能 | 4.1.3.5 | x | |||
| - アプリケーション層に使用されたローカルIPアドレスを通知 | 4.1.3.5 | x | |||
| 無効なIP送信元アドレスはUDP/IPによって静かに破棄 | 4.1.3.6 | x | |||
| 有効なIP送信元アドレスのみ送信 | 4.1.3.6 | x | |||
| UDPアプリケーションインターフェースサービス | |||||
| アプリケーションに3.4節の完全なIPインターフェースを提供 | 4.1.4 | x | |||
| - データグラム送信時にTTL、TOS、IPオプションを指定可能 | 4.1.4 | x | |||
| - 受信したTOSをアプリケーション層に渡す | 4.1.4 | x |
4.2 伝送制御プロトコル -- TCP (TRANSMISSION CONTROL PROTOCOL -- TCP)
4.2.1 はじめに (INTRODUCTION)
伝送制御プロトコル (Transmission Control Protocol, TCP) [TCP:1] は、インターネットスイートの主要な仮想回路トランスポートプロトコルです。TCPは、全二重8ビットバイトストリームの信頼性のある順序付き配信を提供します。TCPは、メール (SMTP)、ファイル転送 (FTP)、仮想端末サービス (Telnet) など、信頼性のあるコネクション指向トランスポートサービスを必要とするアプリケーションによって使用されます。これらのアプリケーション層プロトコルの要件は、[INTRO:1]で説明されています。
4.2.2 プロトコルウォークスルー (PROTOCOL WALK-THROUGH)
4.2.2.1 ウェルノウンポート (Well-Known Ports): RFC-793 第2.7節
議論 (DISCUSSION):
TCPは、インターネット上で標準化されたサービスにアクセスするために、0~255の範囲のポート番号を「ウェルノウン」ポート用に予約しています。残りのポート空間は、アプリケーションプロセスに自由に割り当てることができます。現在のウェルノウンポートの定義は、「Assigned Numbers」というタイトルのRFC [INTRO:6] にリストされています。新しいウェルノウンポートを定義するための前提条件は、提案されたサービスを詳細に文書化して新しい実装を可能にするRFCです。
一部のシステムは、TCPポート空間の第3の細分化を追加することによってこの概念を拡張します:予約ポート (reserved ports)。これらは通常、オペレーティングシステム固有のサービスに使用されます。例えば、予約ポートは256とシステム依存の上限の間にある場合があります。一部のシステムは、特権ユーザーのみがこれらのポート値でTCP接続を開くことを許可することによって、ウェルノウンポートと予約ポートを保護することをさらに選択します。ホストがすべてのホストがこの方法で低番号ポートを保護していると仮定しない限り、これは完全に合理的です。
4.2.2.2 プッシュの使用 (Use of Push): RFC-793 第2.8節
PUSH
フラグを設定せずにアプリケーションが一連のSEND呼び出しを発行すると、TCP してもよい (MAY) は内部的にデータを集約して送信しません。同様に、PSHビットのない一連のセグメントを受信すると、TCP してもよい (MAY) は内部的にデータをキューに入れて受信アプリケーションに配信しません。
PSHビットはレコードマーカーではなく、セグメント境界から独立しています。送信側 すべきである (SHOULD) は、データをパケット化する際に連続するPSHビットを折りたたんで、可能な限り大きなセグメントを送信します。
TCP してもよい (MAY) は、SEND呼び出しでPUSHフラグを実装します。PUSHフラグが実装されていない場合、送信TCP:(1) データを無期限にバッファリングしてはならず、(2) しなければならない (MUST) 最後のバッファリングされたセグメント(送信するキューに入っているデータがこれ以上ない場合)でPSHビットを設定します。
RFC-793の48、50、74ページの議論は、受信したPSHフラグをアプリケーション層に渡す必要があることを誤って示唆しています。受信したPSHフラグをアプリケーション層に渡すことは、現在は オプション (OPTIONAL) です。
アプリケーションは、通信デッドロックを回避するためにデータの配信を強制する必要があるときはいつでも、SEND呼び出しでPUSHフラグを設定することを論理的に要求します。ただし、TCP すべきである (SHOULD) は、パフォーマンスを向上させるために可能な限り最大サイズのセグメントを送信します(4.2.3.4節を参照)。
議論 (DISCUSSION):
SEND呼び出しでPUSHフラグが実装されていない場合、つまりアプリケーション/TCPインターフェースが純粋なストリームモデルを使用する場合、合理的なサイズのセグメントを形成するために小さなデータ断片を集約する責任の一部はアプリケーション層にあります。
通常、対話型アプリケーションプロトコルは、少なくとも各コマンドまたは応答シーケンスの最後のSEND呼び出しでPUSHフラグを設定する必要があります。FTPのようなバルク転送プロトコルは、ファイルの最後のセグメントでPUSHフラグを設定するか、バッファデッドロックを防ぐ必要がある場合に設定する必要があります。
受信側では、PSHビットはバッファリングされたデータをアプリケーションに強制的に配信します(完全なバッファよりも少ないデータを受信した場合でも)。逆に、PSHビットがない場合は、不要なアプリケーションプロセスのウェイクアップ呼び出しを回避するために使用できます。これは大規模なタイムシェアリングホストにとって重要なパフォーマンスの最適化である可能性があります。PSHビットを受信アプリケーションに渡すことで、アプリケーション内で同様の最適化が可能になります。
4.2.2.3 ウィンドウサイズ (Window Size): RFC-793 第3.1節
ウィンドウサイズ しなければならない (MUST) は符号なし数として扱われます。そうしないと、大きなウィンドウサイズが負のウィンドウのように見え、TCPは機能しません。推奨される (RECOMMENDED) のは、実装が接続レコード内の送信および受信ウィンドウサイズに32ビットフィールドを予約し、すべてのウィンドウ計算に32ビットを使用することです。
議論 (DISCUSSION):
TCPヘッダー内のウィンドウフィールドは、高速で長遅延のパスには小さすぎることが知られています。ウィンドウサイズを拡張するための実験的なTCPオプションが定義されています。例えば、[TCP:11]を参照してください。このような拡張の採用を予期して、TCP実装者はウィンドウを32ビットとして扱う必要があります。
4.2.2.4 緊急ポインタ (Urgent Pointer): RFC-793 第3.1節
2番目の文にはエラーがあります:緊急ポインタは、緊急データシーケンスの最後のオクテット(LAST+1ではなく)のシーケンス番号を指します。56ページ(最後の文)の説明は正しいです。
TCP しなければならない (MUST) は、任意の長さの緊急データシーケンスをサポートします。
TCP しなければならない (MUST) は、緊急ポインタを受信し以前に保留中の緊急データがない場合、または緊急ポインタがデータストリーム内で前進するたびに、アプリケーション層に非同期に通知します。アプリケーションが接続から読み取る緊急データがまだどれだけあるかを知る方法、または少なくとも緊急データがまだあるかどうかを判断する方法が なければならない (MUST) です。
議論 (DISCUSSION):
緊急メカニズムは任意のアプリケーションで使用できますが、通常はTelnetプログラムに「中断」タイプのコマンドを送信するために使用されます([INTRO:1]の「Telnet同期シーケンスの使用」セクションを参照)。
非同期または「帯域外」通知により、アプリケーションは「緊急モード」に入り、TCP接続からデータを読み取ることができます。これにより、通常の入力バッファが未処理のデータでいっぱいのアプリケーションに制御コマンドを送信できます。
実装 (IMPLEMENTATION):
4.2.4.1節で説明されている汎用ERROR-REPORT()上方呼び出しは、アプリケーションに緊急データの到着を通知する1つの可能なメカニズムです。
4.2.2.5 TCPオプション (TCP Options): RFC-793 第3.1節
TCP しなければならない (MUST) は、任意のセグメントでTCPオプションを受信できます。TCP しなければならない (MUST) は、実装していないTCPオプションをエラーなしで無視します。オプションに長さフィールドがあると仮定します(将来定義されるすべてのTCPオプションには長さフィールドがあります)。TCP しなければならない (MUST) は、クラッシュすることなく不正なオプション長(ゼロなど)を処理する準備ができている必要があります。推奨される手順は、接続をリセットして理由を記録することです。
4.2.2.6 最大セグメントサイズオプション (Maximum Segment Size Option): RFC-793 第3.1節
TCP しなければならない (MUST) は、最大セグメントサイズ (Maximum Segment Size, MSS) オプション [TCP:4] の送信と受信を実装します。
TCP すべきである (SHOULD) は、受信MSSがデフォルト値536と異なる場合、各SYNセグメントでMSS(最大セグメントサイズ)オプションを送信し、常に送信 してもよい (MAY) です。
接続確立時にMSSオプションを受信しなかった場合、TCP しなければならない (MUST) はデフォルトの送信MSSを536(576-40)[TCP:4]と仮定します。
TCPが実際に送信するセグメントの最大サイズ、「有効送信MSS」は、送信MSS(リモートホストの利用可能な再組み立てバッファサイズを反映)とIP層が許可する最大サイズの小さい方 でなければなりません (MUST):
Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize
ここで:
- SendMSS は、リモートホストから受信したMSS値、またはMSSオプションが受信されなかった場合はデフォルト値536です。
- MMS_S は、TCPが送信できるトランスポート層メッセージの最大サイズです。
- TCPhdrsize は、TCPヘッダーのサイズです。これは通常20ですが、TCPオプションを送信する場合はもっと大きくなる可能性があります。
- IPoptionsize は、TCPが現在のメッセージとともにIP層に渡すIPオプションのサイズです。
MSSオプションで送信するMSS値は、以下以下でなければなりません:
MMS_R - 20
ここで MMS_R は、受信(および再組み立て)できるトランスポート層メッセージの最大サイズです。TCPは、IP層からMMS_RとMMS_Sを取得します。3.4節の汎用呼び出しGET_MAXSIZESを参照してください。
議論 (DISCUSSION):
TCPセグメントサイズの選択は、パフォーマンスに強い影響を与えます。大きなセグメントは、ヘッダーサイズとデータグラムごとの処理オーバーヘッドをより多くのデータバイトに償却することでスループットを向上させます。ただし、パケットが大きすぎてIPフラグメンテーションが発生すると、いずれかのフラグメントが失われた場合に効率が急激に低下します [IP:9]。
一部のTCP実装は、宛先ホストが非接続ネットワーク上にある場合にのみMSSオプションを送信します。ただし、一般的にTCP層にはこの決定を行うための適切な情報がない可能性があるため、インターネットパスの適切なMTUを決定するタスクをIP層に任せる方が良いでしょう。したがって、TCPは常にオプションを送信し(536でない場合)、IP層は3.3.3と3.4で規定されているようにMMS_Rを決定することをお勧めします。提案されているMTUを測定するためのIP層メカニズムは、TCPを変更せずにIP層を変更します。
4.2.2.7 TCPチェックサム (TCP Checksum): RFC-793 第3.1節
UDPチェックサム(4.1.3.4節を参照)とは異なり、TCPチェックサムは決してオプションではありません。送信側 しなければならない (MUST) はそれを生成し、受信側 しなければならない (MUST) はそれをチェックします。
4.2.2.8 TCP接続状態図 (TCP Connection State Diagram): RFC-793 第3.2節、23ページ
この図にはいくつかの問題があります:
(a) SYN-SENTからSYN-RCVDへの矢印は、68ページのテキストと図8と一致するように「snd SYN,ACK」とラベル付けする必要があります。
(b) 受動オープン後にRSTを受信した場合(テキスト70ページを参照)、SYN-RCVD状態からLISTEN状態への矢印がある可能性があります。
(c) FIN-WAIT-1状態からTIME-WAIT状態に直接移行することができます(仕様の75ページを参照)。
4.2.2.9 初期シーケンス番号選択 (Initial Sequence Number Selection): RFC-793 第3.3節、27ページ
TCP しなければならない (MUST) は、指定されたクロック駆動の初期シーケンス番号選択を使用します。
4.2.2.10 同時オープン試行 (Simultaneous Open Attempts): RFC-793 第3.4節
図8にエラーがあります:7行目のパケットは5行目のパケットと同一である必要があります。
TCP しなければならない (MUST) は同時オープン試行をサポートします。
議論 (DISCUSSION):
実装者が驚くことがあるのは、2つのアプリケーションが相互に同時に接続しようとすると、2つではなく1つの接続のみが生成されることです。これは意図的な設計決定です。「修正」しようとしないでください。
4.2.2.11 古い重複SYNからの回復 (Recovery from Old Duplicate SYN): RFC-793 第3.4節、33ページ
TCP実装 しなければならない (MUST) は、接続が受動OPENまたは能動OPENの結果としてSYN_RCVD状態に達したかどうかを追跡します。
4.2.2.12 RSTセグメント (RST Segment): RFC-793 第3.4節
TCP すべきである (SHOULD) は、受信したRSTセグメントにデータを含めることを許可します。
議論 (DISCUSSION):
RSTセグメントにRSTの原因をエンコードおよび説明するASCIIテキストを含めることができると提案されています。そのようなデータの標準はまだ確立されていません。
4.2.2.13 接続のクローズ (Closing a Connection): RFC-793 第3.5節
TCP接続は2つの方法で終了する可能性があります:(1) FINハンドシェイクを使用する通常のTCPクローズシーケンス、および (2) 1つ以上のRSTセグメントが送信され、接続状態がただちに破棄される「中止」。TCP接続がリモートサイトによってクローズされた場合、ローカルアプリケーション しなければならない (MUST) は、それが正常にクローズされたか中止されたかを通知されます。
通常のTCPクローズシーケンスは、両方向でバッファリングされたデータを確実に配信します。TCP接続の2つの方向は独立してクローズされるため、接続は「半クローズ」、つまり一方向のみでクローズされた状態になる可能性があり、ホストは半クローズ接続のオープン方向でデータを送信し続けることが許可されています。
ホスト してもよい (MAY) は「半二重」TCPクローズシーケンスを実装します。これにより、CLOSEを呼び出したアプリケーションは接続からデータを読み取り続けることができません。そのようなホストがTCPで受信データがまだ保留中の間にCLOSE呼び出しを発行した場合、またはCLOSEが呼び出された後に新しいデータが受信された場合、そのTCP すべきである (SHOULD) はデータが失われたことを示すためにRSTを送信します。
接続が能動的にクローズされるとき、それ しなければならない (MUST) は2×MSL(最大セグメント寿命)の時間、TIME-WAIT状態に留まります。ただし、次の条件を満たす場合、リモートTCPからの新しいSYNを受け入れて してもよい (MAY) 、TIME-WAIT状態から直接接続を再オープンします:
(1) 新しい接続の初期シーケンス番号を、以前の接続化身で使用した最大シーケンス番号よりも大きく割り当て、かつ
(2) SYNが古い重複であることが判明した場合、TIME-WAIT状態に戻ります。
議論 (DISCUSSION):
TCPのフル二重データ保存クローズは、類似のISOトランスポートプロトコルTP4には含まれていない機能です。
一部のシステムは半クローズ接続を実装していません。おそらく、特定のオペレーティングシステムのI/Oモデルに適合しないためです。これらのシステムでは、アプリケーションがCLOSEを呼び出すと、接続から入力データを読み取ることができなくなります。これは「半二重」TCPクローズシーケンスと呼ばれます。
TCPの優雅なクローズアルゴリズムは、接続の(少なくとも)一端で、2×MSL、つまり4分のタイムアウト期間、接続状態が定義されたままである必要があります。この期間中、接続を定義する(リモートソケット、ローカルソケット)ペアはビジーであり、再利用できません。特定のポートペアが占有される時間を短縮するために、一部のTCPはTIME-WAIT状態で新しいSYNを受け入れることを許可します。
4.2.2.14 データ通信 (Data Communication): RFC-793 第3.7節、40ページ
RFC-793が書かれて以来、効率的なデータ通信を実現するためのTCPアルゴリズムに関する広範な作業が行われてきました。本ドキュメントの後のセクションでは、データを送信するタイミング(4.2.3.4節)、確認応答を送信するタイミング(4.2.3.2節)、およびウィンドウを更新するタイミング(4.2.3.3節)を決定するための必要かつ推奨されるTCPアルゴリズムについて説明します。
議論 (DISCUSSION):
重要なパフォーマンスの問題の1つは、「糊涂窗口综合症」または「SWS」[TCP:5]です。これは、小さな増分ウィンドウ移動の安定したパターンであり、TCP性能が極めて低下します。SWSを回避するためのアルゴリズムは、送信側(4.2.3.4節)と受信側(4.2.3.3節)の両方について以下で説明されています。
簡単に言うと、SWSは、受信側が新しいバッファ空間が利用可能になるたびに右ウィンドウエッジを前進させ、送信側がどんなに小さくても増分ウィンドウを使用してさらにデータを送信することによって引き起こされます [TCP:5]。結果として、送信側と受信側の両方が接続用の大きな総バッファ空間を持っているにもかかわらず、微小なデータセグメントを送信する安定したパターンになる可能性があります。SWSは、大量のデータの送信中にのみ発生する可能性があります。接続が静止状態になると、問題は消えます。これは、ウィンドウ管理の典型的な単純な実装によって引き起こされますが、以下に示す送信側と受信側のアルゴリズムはそれを回避します。
もう1つの重要なTCP性能問題は、一部のアプリケーション、特に文字単位のホストへのリモートログインが、1オクテットのデータセグメントのストリームを送信する傾向があることです。デッドロックを避けるために、そのようなアプリケーションからのすべてのTCP SEND呼び出しは、アプリケーションによって明示的に、またはTCPによって暗黙的に「プッシュ」される必要があります。結果として、各データオクテットを含む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 再送信タイムアウト (Retransmission Timeout): RFC-793 第3.7節、41ページ
RFC-793で再送信タイムアウトを計算するために提案されたアルゴリズムは、現在不十分であることが知られています。以下の4.2.3.1節を参照してください。
Jacobson [TCP:7]によるインターネット輻輳とTCP再送信安定性に関する最近の研究は、「スロースタート」と「輻輳回避」を組み合わせた送信アルゴリズムを生み出しました。TCP しなければならない (MUST) はこのアルゴリズムを実装します。
再送信されたパケットが元のパケットと同一である場合(データ境界が変更されていないだけでなく、ヘッダーのウィンドウと確認応答フィールドも変更されていないことを意味します)、同じIP識別フィールド してもよい (MAY) を使用できます(3.2.1.5節を参照)。
実装 (IMPLEMENTATION):
一部のTCP実装者は、データストリームを「パケット化」することを選択しています。つまり、セグメントが最初に送信されるときにセグメント境界を選択し、これらのセグメントが確認応答されるまで「再送信キュー」にキューイングします。別の設計(おそらくより簡単)は、データが送信または再送信されるたびにパケット化を延期することです。したがって、セグメント再送信キューはありません。
セグメント再送信キューを持つ実装では、最初の再送信タイムアウトが発生したときに確認応答を待っているセグメントを再パケット化することにより、TCP性能を向上させることができます。つまり、適合する未処理のセグメントは、新しいIP識別値を持つ1つの最大サイズのセグメントに結合されます。次に、TCPは、この結合されたセグメントが確認応答されるまで再送信キューに保持します。ただし、再送信キュー内の最初の2つのセグメントの合計が1つの最大サイズのセグメントを超える場合、TCPは元のIP識別フィールドを使用して最初のセグメントのみを再送信します。
4.2.2.16 ウィンドウの管理 (Managing the Window): RFC-793 第3.7節、41ページ
TCP受信側 すべきではない (SHOULD NOT) はウィンドウを縮小します。つまり、右ウィンドウエッジを左に移動します。ただし、送信TCP しなければならない (MUST) はウィンドウの縮小に対して堅牢であり、これにより「使用可能ウィンドウ」(4.2.3.4節を参照)が負になる可能性があります。
これが発生した場合、送信側 すべきではない (SHOULD NOT) は新しいデータを送信しますが、SND.UNAとSND.UNA+SND.WNDの間の古い未確認データを通常どおり再送信 すべきである (SHOULD) です。送信側 してもよい (MAY) はSND.UNA+SND.WNDを超える古いデータも再送信しますが、右ウィンドウエッジを超えるデータが確認応答されない場合、接続をタイムアウト すべきではない (SHOULD NOT) です。ウィンドウがゼロに縮小した場合、TCP しなければならない (MUST) は標準的な方法でそれを探査します(次のセクションを参照)。
議論 (DISCUSSION):
データがより大きなウィンドウに送信された後、ウィンドウが右から縮小すると、多くのTCP実装が混乱します。TCPには、データグラムの再順序付けの可能性があるにもかかわらず、最新のウィンドウ更新を選択するヒューリスティックがあることに注意してください。その結果、シーケンス番号も確認応答番号も増加していない場合、以前に提供されたものよりも小さいウィンドウのウィンドウ更新を無視する可能性があります。
4.2.2.17 ゼロウィンドウの探査 (Probing Zero Windows): RFC-793 第3.7節、42ページ
ゼロ(提供された)ウィンドウの探査 しなければならない (MUST) はサポートされます。
TCP してもよい (MAY) は、提供された受信ウィンドウを無期限に閉じたままにします。受信TCPが探査セグメントに応答して確認応答を送信し続ける限り、送信TCP しなければならない (MUST) は接続を開いたままにすることを許可します。
議論 (DISCUSSION):
データを含まないACK(確認応答)セグメントはTCPによって確実に送信されないことを覚えておくことが非常に重要です。ゼロウィンドウ探査がサポートされていない場合、ウィンドウを再オープンするACKセグメントが失われると、接続が永久にハングする可能性があります。
ゼロウィンドウを開く遅延は、一般的に受信アプリケーションがそのTCPからデータを取得するのを停止したときに発生します。たとえば、プリンターが用紙切れになったために停止したプリンターデーモンアプリケーションを考えてみてください。
送信ホスト すべきである (SHOULD) は、ゼロウィンドウが再送信タイムアウト期間(4.2.2.15節を参照)存在したときに最初のゼロウィンドウ探査を送信し、連続する探査間の間隔を指数関数的に増やす すべきである (SHOULD) です。
議論 (DISCUSSION):
この手順は、ゼロウィンドウ状態がウィンドウオープニング更新を含む失われたACKセグメントによるものである場合、遅延を最小限に抑えます。指数バックオフが推奨され、ここで指定されていない最大間隔がある可能性があります。この手順は再送信アルゴリズムの手順に似ており、実装で2つの手順を組み合わせることができる可能性があります。
4.2.2.18 受動OPEN呼び出し (Passive OPEN Calls): RFC-793 第3.8節
すべての受動OPEN呼び出しは、LISTEN状態で新しい接続レコードを作成するか、エラーを返します。以前に作成された接続レコードに影響を与えては なりません (MUST NOT)。
複数の同時ユーザーをサポートするTCP しなければならない (MUST) は、同じローカルポートを持つ接続ブロックがSYN-SENTまたはSYN-RECEIVED状態にある間、アプリケーションがポートでLISTENできるようにするOPEN呼び出しを機能的に提供します。
議論 (DISCUSSION):
一部のアプリケーション(SMTPサーバーなど)は、ほぼ同時に複数の接続試行を処理する必要がある場合があります。アプリケーションに、以前の接続試行が3ウェイハンドシェイクを経ている間に新しい接続をリッスンする手段を提供することにより、接続試行が失敗する確率が低下します。
実装 (IMPLEMENTATION):
同時オープンの許容可能な実装は、複数の受動OPEN呼び出しを許可するか、単一の受動OPEN呼び出しからLISTEN状態接続の「クローン」を許可する場合があります。
4.2.2.19 生存時間 (Time to Live): RFC-793 第3.9節、52ページ
RFC-793は、TCPがIP層にTTL = 60でTCPセグメントを送信するよう要求することを指定していました。これは時代遅れです。TCPセグメントを送信するために使用されるTTL値 しなければならない (MUST) は設定可能です。議論については3.2.1.7節を参照してください。
4.2.2.20 イベント処理 (Event Processing): RFC-793 第3.9節
厳密には必須ではありませんが、TCP すべきである (SHOULD) は順序外TCPセグメントをキューイングできます。70ページの最初の段落の最後の文の「may」を「should」に変更してください。
議論 (DISCUSSION):
限られたバッファ空間のため、一部の小規模ホスト実装はセグメントキューイングを省略しています。この省略は、TCPスループットに悪影響を与えることが予想されます。単一セグメントの損失により、後続のすべてのセグメントが「順序外」に見えるためです。
一般に、受信セグメントの処理 しなければならない (MUST) は、可能な限りACKセグメントを集約するように実装されます。たとえば、TCPがキューイングされたセグメントのシリーズを処理している場合、ACKセグメントを送信する前にそれらすべてを処理 しなければならない (MUST) です。
以下は、RFC-793のイベント処理セクションに関するいくつかの詳細なエラー訂正と注記です。
(a) CLOSE呼び出し、CLOSE-WAIT状態、61ページ:CLOSINGではなく、LAST-ACK状態に入ります。
(b) LISTEN状態、SYNのチェック(65、66ページ):SYNビットがある場合、セグメントのセキュリティ/コンパートメントまたは優先順位が間違っている場合、リセットが送信されます。テキストに示されているリセットの形式は間違っています。次のようにする必要があります:
<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>
(c) SYN-SENT状態、SYNのチェック、68ページ:接続がESTABLISHED状態に入ると、次の変数を設定する必要があります:
SND.WND <- SEG.WND
SND.WL1 <- SEG.SEQ
SND.WL2 <- SEG.ACK
(d) セキュリティと優先順位のチェック、71ページ:最初の見出し「ESTABLISHED STATE」は、実際にはSYN-RECEIVED以外のすべての状態のリストである必要があります:ESTABLISHED、FIN-WAIT-1、FIN-WAIT-2、CLOSE-WAIT、CLOSING、LAST-ACK、およびTIME-WAIT。
(e) SYNビットのチェック、71ページ:「SYN-RECEIVED状態で、接続が受動OPENで開始された場合、この接続をLISTEN状態に戻して戻ります。それ以外の場合...」。
(f) ACKフィールドのチェック、SYN-RECEIVED状態、72ページ:接続がESTABLISHED状態に入ると、(c)にリストされている変数を設定する必要があります。
(g) ACKフィールドのチェック、ESTABLISHED状態、72ページ:SEG.ACK =< SND.UNA(=が省略されました)の場合、ACKは重複です。同様に、SND.UNA =< SEG.ACK =< SND.NXTの場合、ウィンドウを更新する必要があります。
(h) USER TIMEOUT、77ページ:
TCPに接続を強制的に閉じさせるのではなく、アプリケーションにタイムアウトを通知する方が良いでしょう。ただし、4.2.3.5節も参照してください。
4.2.2.21 キューイングされたセグメントの確認応答 (Acknowledging Queued Segments): RFC-793 第3.9節
TCP してもよい (MAY) は、ウィンドウ内にあるが左ウィンドウエッジにない有効なセグメントが到着したときに、RCV.NXTを確認応答するACKセグメントを送信します。
議論 (DISCUSSION):
RFC-793(74ページを参照)は、順序外セグメントが受信されたとき、つまりSEG.SEQがRCV.NXTと等しくないときに、ACKセグメントを送信すべきかどうかについて曖昧でした。
順序外セグメントをACKする理由の1つは、「高速再送信」として知られる実験的アルゴリズムをサポートすることです。このアルゴリズムでは、送信側は「冗長」ACKを使用して、再送信タイマーが期限切れになる前にセグメントが失われたと推測します。SEG.ACKの同じ値と同じ右ウィンドウエッジで受信されたACKの数をカウントします。しきい値を超える数のそのようなACKが受信された場合、SEG.ACKから始まるオクテットを含むセグメントは失われたと見なされ、タイムアウトを待たずに再送信されます。しきい値は、インターネットで可能性のある最大セグメント再順序付けを補償するように選択されます。高速再送信アルゴリズムがどの程度有用であるかを判断するには、まだ十分な経験がありません。
4.2.3 特定の問題 (SPECIFIC ISSUES)
4.2.3.1 再送信タイムアウト計算 (Retransmission Timeout Calculation)
ホストTCP しなければならない (MUST) は、再送信タイムアウト(「RTO」)を計算するために、Karnのアルゴリズムとjacobsonのアルゴリズムを実装します。
-
Jacobsonのアルゴリズムは、スムーズなラウンドトリップ(「RTT」)時間を計算するための簡単な分散測定を組み込んでいます [TCP:7]。
-
KarnのアルゴリズムはRTT測定を選択するためのもので、曖昧なラウンドトリップ時間がスムーズなラウンドトリップ時間の計算を破損しないようにします [TCP:6]。
この実装には、同じセグメントの連続するRTO値の「指数バックオフ」も含める しなければならない (MUST) です。SYNセグメントの再送信 すべきである (SHOULD) は、データセグメントと同じアルゴリズムを使用します。
議論 (DISCUSSION):
RFC-793で指定されたRTO計算には、2つの既知の問題がありました。まず、再送信がある場合、RTTの正確な測定は困難です。次に、スムーズなラウンドトリップ時間を計算するアルゴリズムは不十分です [TCP:7]。RTT値の分散が小さく一定であると誤って仮定していたためです。これらの問題は、それぞれKarnのアルゴリズムとJacobsonのアルゴリズムによって解決されました。
これらの改善の使用によるパフォーマンスの向上は、顕著なものから劇的なものまでさまざまです。測定されたRTT分散を組み込むJacobsonのアルゴリズムは、低速リンクで特に重要です。パケットサイズの自然な変動により、RTTに大きな変動が生じるためです。あるベンダーは、TCPでJacobsonの分散アルゴリズムを実装した結果、9.6kbラインのリンク利用率が10%から90%に上昇したことを発見しました。
新しい接続の推定パラメータを初期化するには、次の値を使用 すべきです (SHOULD):
(a) RTT = 0秒。
(b) RTO = 3秒。(スムーズな分散は、このRTOになる値に初期化されます)。
RTOの推奨される上限と下限は、大規模なインターネットでは不十分であることが知られています。下限 すべきである (SHOULD) は秒の端数で測定され(高速LANに対応するため)、上限は2×MSL、つまり240秒である必要があります。
議論 (DISCUSSION):
経験により、これらの初期化値は合理的であり、いずれにせよKarnおよびJacobsonのアルゴリズムは、TCP動作を初期パラメータの選択に対してかなり鈍感にすることが示されています。
4.2.3.2 いつACKセグメントを送信するか (When to Send an ACK Segment)
TCPデータセグメントのストリームを受信しているホストは、受信したデータセグメントごとに1つ未満のACK(確認応答)セグメントを送信することにより、インターネットとホストの両方の効率を高めることができます。これは「遅延ACK」として知られています [TCP:5]。
TCP すべきである (SHOULD) は遅延ACKを実装しますが、ACKを過度に遅延させてはなりません。特に、遅延 しなければならない (MUST) は0.5秒未満であり、完全サイズのセグメントのストリームでは、少なくとも2番目ごとのセグメントにACKがある すべきです (SHOULD)。
議論 (DISCUSSION):
遅延ACKは、アプリケーションにウィンドウを更新し、おそらく即座に応答を送信する機会を与えます。特に、文字モードのリモートログインの場合、遅延ACKは、サーバーが送信するセグメントの数を3分の1に減らすことができます(ACK、ウィンドウ更新、エコー文字がすべて1つのセグメントに結合されます)。
さらに、一部の大規模なマルチユーザーホストでは、遅延ACKは、処理するパケットの総数を減らすことにより、プロトコル処理のオーバーヘッドを大幅に削減できます [TCP:5]。ただし、ACKの過度の遅延は、ラウンドトリップタイミングとパケット「クロッキング」アルゴリズムを妨げる可能性があります [TCP:7]。
4.2.3.3 いつウィンドウ更新を送信するか (When to Send a Window Update)
TCP しなければならない (MUST) は、受信側にSWS回避アルゴリズムを含めます [TCP:5]。
実装 (IMPLEMENTATION):
受信側のSWS回避アルゴリズムは、右ウィンドウエッジをいつ前進させることができるかを決定します。これは通常「ウィンドウの更新」として知られています。このアルゴリズムは、遅延ACKアルゴリズム(4.2.3.2節を参照)と組み合わせて、現在のウィンドウを含むACKセグメントがいつ実際に受信側に送信されるかを決定します。RFC-793の表記を使用します。そのドキュメントの図4と5を参照してください。
受信側SWSの解決策は、ネットワークから小さなセグメントでデータを受信した場合でも、右ウィンドウエッジRCV.NXT+RCV.WNDを小さな増分で前進させることを避けることです。
総受信バッファ空間がRCV.BUFFであると仮定します。任意の瞬間に、このうちRCV.USERオクテットが、受信されて確認応答されたがユーザープロセスがまだ消費していないデータと結びついている可能性があります。接続が静止しているとき、RCV.WND = RCV.BUFFおよびRCV.USER = 0です。
データが到着して確認応答されるときに右ウィンドウエッジを固定したままにするには、受信側が完全なバッファ空間よりも少ないものを提供する必要があります。つまり、受信側は、RCV.NXTが増加するにつれてRCV.NXT+RCV.WNDを一定に保つRCV.WNDを指定する必要があります。したがって、総バッファ空間RCV.BUFFは一般的に3つの部分に分割されます:
|<------- RCV.BUFF ---------------->|
1 2 3
----|---------|------------------|------|----
RCV.NXT ^
(Fixed)
1 - RCV.USER = 受信されたがまだ消費されていないデータ;
2 - RCV.WND = 送信側に通知された空間;
3 - Reduction = 利用可能だがまだ通知されていない空間。
受信側の推奨SWS回避アルゴリズムは、削減が次の条件を満たすまでRCV.NXT+RCV.WNDを固定したままにすることです:
RCV.BUFF - RCV.USER - RCV.WND >= min(Fr * RCV.BUFF, Eff.snd.MSS)
ここで、Frは分数で推奨値は1/2であり、Eff.snd.MSSは4.2.2.6節で定義されている有効送信MSSです。不等式が満たされると、RCV.WNDはRCV.BUFF-RCV.USERに設定されます。
このアルゴリズムの一般的な効果は、Eff.snd.MSSの増分でRCV.WNDを前進させることです(現実的な受信バッファの場合:Eff.snd.MSS < RCV.BUFF/2)。また、受信側が送信側と同じであると仮定して、独自のEff.snd.MSSを使用する必要があることに注意してください。
4.2.3.4 いつデータを送信するか (When to Send Data)
TCP しなければならない (MUST) は、送信側にSWS回避アルゴリズムを含めます。
TCP すべきである (SHOULD) は、短いセグメントを結合するためにNagleアルゴリズム [TCP:9] を実装します。ただし、アプリケーションが個々の接続でNagleアルゴリズムを無効にする方法が なければなりません (MUST)。すべての場合において、データの送信はスロースタートアルゴリズム(4.2.2.15節)によって課される制限にも従います。
議論 (DISCUSSION):
Nagleアルゴリズムは一般的に次のとおりです:
未確認データがある場合(つまり、SND.NXT > SND.UNA)、送信TCPは、未処理のデータが確認応答されるか、TCPが完全サイズのセグメント(Eff.snd.MSSバイト; 4.2.2.6節を参照)を送信できるようになるまで、すべてのユーザーデータをバッファリングします(PSHビットに関係なく)。
一部のアプリケーション(リアルタイムディスプレイウィンドウ更新など)では、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 Connection Failures)
TCPによる同じセグメントの過度の再送信は、リモートホストまたはインターネットパスの何らかの失敗を示します。この失敗は短期または長期である可能性があります。次の手順 しなければならない (MUST) を使用して、データセグメントの過度の再送信を処理します [IP:11]:
(a) 同じセグメントに対して発生した再送信の量を測定する2つのしきい値R1とR2があります。R1とR2は、時間単位または再送信のカウントとして測定される場合があります。
(b) 同じセグメントの送信回数がしきい値R1に達するかそれを超える場合、負の助言(3.3.1.4節を参照)をIP層に渡して、デッドゲートウェイ診断をトリガーします。
(c) 同じセグメントの送信回数がR1より大きいしきい値R2に達すると、接続を閉じます。
(d) アプリケーション しなければならない (MUST) は、特定の接続のR2の値を設定できます。たとえば、対話型アプリケーションは、R2を「無限大」に設定して、ユーザーがいつ切断するかを制御できるようにする場合があります。
(e) TCP すべきである (SHOULD) は、R1に達し、R2の前に配信問題をアプリケーションに通知します(そのような情報がアプリケーションによって無効にされていない限り; 4.2.4.1節を参照)。これにより、たとえば、リモートログイン(ユーザーTelnet)アプリケーションプログラムがユーザーに通知できるようになります。
R1の値 すべきである (SHOULD) は、現在のRTOで少なくとも3回の再送信に対応します。R2の値 すべきである (SHOULD) は少なくとも100秒に対応します。
TCP接続を開く試行は、SYNセグメントの過度の再送信、またはRSTセグメントまたはICMPポート到達不能の受信により失敗する可能性があります。SYN再送信 しなければならない (MUST) は、アプリケーション層への通知を含め、データ再送信について説明したばかりの一般的な方法で処理されます。
ただし、SYNとデータセグメントのR1とR2の値は異なる場合があります。特に、SYNセグメントのR2 しなければならない (MUST) は、少なくとも3分間セグメントの再送信を提供するのに十分な大きさに設定されます。もちろん、アプリケーションは接続を早期に閉じる(つまり、オープン試行を諦める)ことができます。
議論 (DISCUSSION):
一部のインターネットパスには重要なセットアップ時間があり、そのようなパスの数は将来増加する可能性があります。
4.2.3.6 TCPキープアライブ (TCP Keep-Alives)
実装者 してもよい (MAY) は、TCP実装に「キープアライブ」を含めることができますが、この慣行は普遍的に受け入れられていません。キープアライブが含まれている場合、アプリケーション しなければならない (MUST) は、各TCP接続に対してそれらをオンまたはオフにすることができ、それらはデフォルトでオフである しなければならない (MUST) です。
キープアライブパケット しなければならない (MUST) は、接続の間隔内でデータまたは確認応答パケットが受信されていない場合にのみ送信されます。この間隔 しなければならない (MUST) は設定可能であり、2時間以上にデフォルト設定 しなければならない (MUST) です。
データを含まないACKセグメントはTCPによって確実に送信されないことを覚えておくことが非常に重要です。したがって、キープアライブメカニズムが実装されている場合、特定のプローブへの応答の失敗を死んだ接続として解釈してはならない してはならない (MUST NOT)。
実装 すべきである (SHOULD) は、データなしのキープアライブセグメントを送信します。ただし、誤ったTCP実装との互換性のため、1つのガベージオクテットを含むキープアライブセグメントを送信するように構成可能 してもよい (MAY) です。
議論 (DISCUSSION):
「キープアライブ」メカニズムは、接続が他の方法でアイドル状態の場合、つまり送信するデータがない場合でも、接続のもう一方の端を定期的に調査します。TCP仕様には、キープアライブメカニズムが含まれていません。なぜなら、それは次のことができるからです:(1) 一時的なインターネット障害中に完全に良好な接続を破る; (2) 不要な帯域幅を消費する(「誰も接続を使用していない場合、それがまだ良好かどうか誰が気にするか?」); (3) パケットに課金するインターネットパスの費用がかかる。
ただし、一部のTCP実装にはキープアライブメカニズムが含まれています。アイドル接続がまだアクティブであることを確認するために、これらの実装は、ピアTCPからの応答を引き出すように設計されたプローブセグメントを送信します。そのようなセグメントには、通常、SEG.SEQ = SND.NXT-1が含まれ、1つのガベージオクテットのデータが含まれている場合と含まれていない場合があります。静かな接続ではSND.NXT = RCV.NXTであるため、このSEG.SEQはウィンドウの外側にあることに注意してください。したがって、プローブは受信側に確認応答セグメントを返し、接続がまだ生きていることを確認します。ピアがネットワークパーティションまたはクラッシュのために接続をドロップした場合、確認応答セグメントではなくRSTで応答します。
残念ながら、一部の不正な動作をするTCP実装は、セグメントにデータが含まれていない限り、SEG.SEQ = SND.NXT-1のセグメントに応答できません。あるいは、実装は、ピアがガベージデータオクテットなしでキープアライブパケットに正しく応答したかどうかを判断できます。
TCPキープアライブメカニズムは、クライアントがクラッシュするかネットワーク障害中に接続を中止した場合に、無期限にハングして不必要にリソースを消費する可能性のあるサーバーアプリケーションでのみ呼び出す必要があります。
4.2.3.7 TCPマルチホーミング (TCP Multihoming)
マルチホームホスト上のアプリケーションがTCP接続を能動的にオープンするときにローカルIPアドレスを指定しない場合、TCP しなければならない (MUST) は(最初の)SYNを送信する前にIP層にローカルIPアドレスの選択を要求します。3.4節の関数GET_SRCADDR()を参照してください。
他のすべての時点で、以前のセグメントがこの接続で送信または受信されており、TCP しなければならない (MUST) は、それらの以前のセグメントで使用されたのと同じローカルアドレスを使用します。
4.2.3.8 IPオプション (IP Options)
受信したオプションがIP層からTCPに渡されるとき、TCP しなければならない (MUST) は理解できないオプションを無視します。
TCP してもよい (MAY) はタイムスタンプとレコードルートオプションをサポートします。
アプリケーション しなければならない (MUST) は、TCP接続を能動的にオープンするときにソースルートを指定でき、これはデータグラムで受信されたソースルートよりも優先 しなければならない (MUST) です。
TCP接続が受動的にOPENされ、完了したIPソースルートオプション(リターンルートを含む)を含むパケットが到着すると、TCP しなければならない (MUST) はリターンルートを保存し、この接続で送信されるすべてのセグメントに使用します。後のセグメントで異なるソースルートが到着した場合、後の定義 すべきである (SHOULD) は以前の定義を上書きします。
4.2.3.9 ICMPメッセージ (ICMP Messages)
TCP しなければならない (MUST) は、IP層から渡されたICMPエラーメッセージに対して行動し、エラーを作成した接続にそれを向けます。必要な逆多重化情報は、ICMPメッセージに含まれるIPヘッダーにあります。
-
ソース抑制 (Source Quench)
TCP しなければならない (MUST) は、接続の送信を遅くすることによってソース抑制に反応します。推奨される (RECOMMENDED) 手順は、ソース抑制が再送信タイムアウトが発生したかのように「スロースタート」をトリガーすることです。
-
宛先到達不能 (Destination Unreachable) -- コード0、1、5
これらの到達不能メッセージはソフトエラー条件を示すため、TCP してはならない (MUST NOT) は接続を中止し、情報をアプリケーションに利用可能にする すべきです (SHOULD)。
議論 (DISCUSSION):
TCPは、ERROR_REPORTルーチンへの上方呼び出しでソフトエラー条件をアプリケーション層に直接報告することも、メッセージを単に記録して、TCP接続がタイムアウトする場合にのみアプリケーションに報告することもできます。
-
宛先到達不能 (Destination Unreachable) -- コード2-4
これらはハードエラー条件であるため、TCP すべきである (SHOULD) は接続を中止します。
-
時間超過 (Time Exceeded) -- コード0、1
これは、宛先到達不能コード0、1、5と同じ方法で処理する必要があります(上記を参照)。
-
パラメータ問題 (Parameter Problem)
これは、宛先到達不能コード0、1、5と同じ方法で処理する必要があります(上記を参照)。
4.2.3.10 リモートアドレス検証 (Remote Address Validation)
TCP実装 しなければならない (MUST) は、無効なリモートIPアドレス(ブロードキャストまたはマルチキャストアドレスなど)へのローカルOPEN呼び出しをエラーとして拒否します。
無効な送信元アドレスを持つ着信SYNは、TCPまたはIP層によって無視される必要があります(3.2.1.3節を参照)。
TCP実装 しなければならない (MUST) は、ブロードキャストまたはマルチキャストアドレスにアドレス指定された着信SYNセグメントを静かに破棄します。
4.2.3.11 TCPトラフィックパターン (TCP Traffic Patterns)
実装 (IMPLEMENTATION):
TCPプロトコル仕様 [TCP:1] は、接続を介したメッセージフローを制御するアルゴリズムの設計において、実装者に大きな自由を与えています -- パケット化、ウィンドウの管理、確認応答の送信など。これらの設計上の決定は、TCPが広範囲のトラフィックパターンに適応する必要があるため困難です。経験により、TCP実装者は2つの極端なトラフィックパターンで設計を検証する必要があることが示されています:
-
単一文字セグメント (Single-character Segments)
送信側がNagleアルゴリズムを使用している場合でも、TCP接続が低遅延LAN経由でリモートログイントラフィックを伝送する場合、受信側は通常、単一文字セグメントのストリームを取得します。リモート端末エコーモードが有効な場合、受信側のシステムは通常、受信した各文字をエコーします。
-
バルク転送 (Bulk Transfer)
TCPがバルク転送に使用される場合、データストリームは(ほぼ)完全に有効MSSのサイズのセグメントで構成される必要があります。TCPはバイト(オクテット)粒度のシーケンス番号空間を使用しますが、バルク転送モードでは、その動作は、TCPがセグメントのみをカウントするシーケンス空間を使用したかのようになる必要があります。
経験により、単一のTCPがこれら2つの極端を効果的かつ効率的に処理できることがさらに示されています。
新しいTCP実装を検証するための最も重要なツールは、パケットトレースプログラムです。他のTCP実装でさまざまなトラフィックパターンをトレースし、結果を注意深く研究することの重要性を示す豊富な経験があります。
4.2.3.12 効率 (Efficiency)
実装 (IMPLEMENTATION):
広範な経験により、TCPの効率的な実装に関する次の提案が得られました:
(a) データをコピーしない (Don't Copy Data)
バルクデータ転送では、主要なCPU集約的タスクは、ある場所から別の場所へのデータのコピーとデータのチェックサムです。TCPデータのコピー数を最小限に抑えることが不可欠です。最終的な速度制限はメモリバス全体でのデータのフェッチである可能性があるため、コピーとチェックサムを組み合わせて、単一のメモリフェッチで両方を実行すると便利な場合があります。
(b) チェックサムルーチンを手作業で作成 (Hand-Craft the Checksum Routine)
優れたTCPチェックサムルーチンは、通常、定義の単純で直接的な実装よりも2~5倍高速です。チェックサムコードを「超高速」にするには、細心の注意と巧妙なコーディングが必要であり、推奨されます。[TCP:10]を参照してください。
(c) 一般的なケースのためのコード (Code for the Common Case)
TCPプロトコル処理は複雑になる可能性がありますが、ほとんどのセグメントでは、いくつかの単純な決定を下すだけで済みます。最も一般的なケースでの決定数を最小限に抑えるようにメインラインをコーディングすることにより、セグメントごとの処理が大幅に高速化されます。
4.2.4 TCP/アプリケーション層インターフェース (TCP/APPLICATION LAYER INTERFACE)
4.2.4.1 非同期レポート (Asynchronous Reports)
ソフトTCPエラー条件をアプリケーションに報告するメカニズムが なければなりません (MUST)。一般的に、これはトランスポート層から非同期に上方呼び出し [INTRO:7] できるアプリケーション提供のERROR_REPORTルーチンの形式をとると仮定します:
ERROR_REPORT(local connection name, reason, subreason)
reasonおよびsubreasonパラメータの正確なエンコーディングは、ここでは指定されていません。ただし、アプリケーションに非同期に報告される条件 しなければならない (MUST) は次のものを含みます:
- ICMPエラーメッセージが到着しました(4.2.3.9を参照)
- 過度の再送信(4.2.3.5を参照)
- 緊急ポインタの前進(4.2.2.4を参照)。
ただし、そのようなERROR_REPORT呼び出しを受信したくないアプリケーションプログラムは、これらの呼び出しを効果的に無効にすることができる すべきです (SHOULD)。
議論 (DISCUSSION):
これらのエラーレポートは、一般的に多くのアプリケーションが無害に無視できるソフトエラーを反映しています。これらのエラーレポート呼び出しはデフォルトで「無効」にすべきだと提案されていますが、これは必須ではありません。
4.2.4.2 サービスタイプ (Type-of-Service)
アプリケーション層 しなければならない (MUST) は、接続で送信されるセグメントのサービスタイプ(TOS)を指定できます。必須ではありませんが、アプリケーション すべきである (SHOULD) は、接続の存続期間中にTOSを変更できます。TCP すべきである (SHOULD) は、接続でセグメントを送信するときに、現在のTOS値を変更せずにIP層に渡します。
TOSは、接続の各方向で独立して指定されるため、受信側アプリケーションはACKセグメントに使用されるTOSを指定します。
TCP してもよい (MAY) は、最近受信したTOSをアプリケーションに渡します。
議論 (DISCUSSION):
一部のアプリケーション(SMTPなど)は、接続の存続期間中に通信の性質を変更するため、TOS仕様を変更したい場合があります。
また、RFC-793で指定されているOPEN呼び出しには、呼び出し側がソースルート、レコードルート、タイムスタンプなどのIPオプションを指定できるパラメータ(「options」)が含まれていることに注意してください。
4.2.4.3 フラッシュ呼び出し (Flush Call)
一部のTCP実装には、FLUSH呼び出しが含まれています。これは、ユーザーがSEND呼び出しを発行したが、まだ送信ウィンドウの右側にあるTCP送信キュー内のすべてのデータを空にします。つまり、シーケンス番号の同期を失うことなく、できるだけ多くのキューイングされた送信データをフラッシュします。これは、Telnetの「出力を中止」機能を実装するのに役立ちます。
4.2.4.4 マルチホーミング (Multihoming)
RFC-793の2.7節と3.8節で概説されているユーザーインターフェースは、マルチホーミング用に拡張する必要があります。OPEN呼び出し しなければならない (MUST) には、次のオプションパラメータがあります:
OPEN( ... [local IP address,] ... )
ローカルIPアドレスの指定を許可します。
議論 (DISCUSSION):
一部のTCPベースのアプリケーションは、特定の接続を開くために使用するローカルIPアドレスを指定する必要があります。FTPはその一例です。
実装 (IMPLEMENTATION):
指定された「ローカルIPアドレス」パラメータを持つ受動OPEN呼び出しは、そのアドレスへの着信接続リクエストを待ちます。パラメータが指定されていない場合、受動OPENは任意のローカルIPアドレスへの着信接続リクエストを待ち、次に接続のローカルIPアドレスを使用される特定のアドレスにバインドします。
能動OPEN呼び出しの場合、指定された「ローカルIPアドレス」パラメータは接続を開くために使用されます。パラメータが指定されていない場合、ネットワークソフトウェアは接続に適切なローカルIPアドレス(3.3.4.2節を参照)を選択します。
4.2.5 TCP要件サマリー (TCP REQUIREMENTS SUMMARY)
| 機能 | 章節 | 必須 (MUST) | すべき (SHOULD) | 可能 (MAY) | してはならない (MUST NOT) |
|---|---|---|---|---|---|
| Pushフラグ | |||||
| 未プッシュデータを集約またはキュー | 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 | |||
| 可能な場合に最大サイズセグメントを送信 | 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 | |||
| 送信側がゼロウィンドウ接続をタイムアウト | 4.2.2.17 | x | |||
| 緊急データ | |||||
| ポインタが最後のオクテットを指す | 4.2.2.4 | x | |||
| 任意長の緊急データシーケンス | 4.2.2.4 | x | |||
| ALPに非同期に緊急データを通知 | 4.2.2.4 | x | |||
| ALPが緊急データがどれだけキューにあるかを知る | 4.2.2.4 | x | |||
| 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 | |||
| クロック駆動のISN選択を使用 | 4.2.2.9 | x | |||
| 接続のオープン | |||||
| 同時オープン試行をサポート | 4.2.2.10 | x | |||
| SYN-RCVDが最後の状態を記憶 | 4.2.2.11 | x | |||
| 受動Open呼び出しが他と干渉 | 4.2.2.18 | x | |||
| 同じポートでの同時LISTEN機能 | 4.2.2.18 | x | |||
| 必要に応じてIPにSYNの送信元アドレスを要求 | 4.2.3.7 | x | |||
| それ以外の場合、接続のローカルアドレスを使用 | 4.2.3.7 | x | |||
| ブロードキャスト/マルチキャストIPアドレスへのOPEN | 4.2.3.10 | x | |||
| ブロードキャスト/マルチキャストアドレスへのセグメントを静かに破棄 | 4.2.3.10 | x | |||
| 接続のクローズ | |||||
| RSTにデータを含めることができる | 4.2.2.12 | x | |||
| アプリケーションに中止された接続を通知 | 4.2.2.13 | x | |||
| 半二重クローズ接続 | 4.2.2.13 | x | |||
| RSTを送信してデータ損失を示す | 4.2.2.13 | x | |||
| TIME-WAIT状態で2×MSL秒 | 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 | |||
| アプリケーションが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 | |||
R1≤再送信<R2をALPに通知 | 4.2.3.5 | x | |||
| R1、R2の推奨値 | 4.2.3.5 | x | |||
| SYNに同じメカニズム | 4.2.3.5 | x | |||
| SYNのR2は少なくとも3分 | 4.2.3.5 | x | |||
| キープアライブパケットの送信 | 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 | |||
| データグラムのソースルートを上書き | 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)→ALPに通知 | 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 | |||
| 時間超過→ALPに通知、中止しない | 4.2.3.9 | x | |||
| パラメータ問題→ALPに通知、中止しない | 4.2.3.9 | x | |||
| アドレス検証 | |||||
| 無効なIPアドレスへのOPEN呼び出しを拒否 | 4.2.3.10 | x | |||
| 無効なIPアドレスからのSYNを拒否 | 4.2.3.10 | x | |||
| ブロードキャスト/マルチキャストアドレスへのSYNを静かに破棄 | 4.2.3.10 | x | |||
| TCP/ALPインターフェースサービス | |||||
| エラーレポートメカニズム | 4.2.4.1 | x | |||
| ALPがエラーレポートルーチンを無効化可能 | 4.2.4.1 | x | |||
| ALPが送信のTOSを指定可能 | 4.2.4.2 | x | |||
| 変更せずにIPに渡す | 4.2.4.2 | x | |||
| ALPが接続中にTOSを変更可能 | 4.2.4.2 | x | |||
| 受信したTOSをALPに渡す | 4.2.4.2 | x | |||
| FLUSH呼び出し | 4.2.4.3 | x | |||
| OPENでオプションのローカルIPアドレスパラメータ | 4.2.4.4 | x |
注釈:
(1) "ALP" はアプリケーション層プログラム (Application-Layer Program) を意味します。