| プロトコルスタック | |
| 略語 | TCP |
|---|---|
| 開発者 | ヴィント・サーフとボブ・カーン |
| 導入 | 1974 (1974年) |
| に基づく | トランスミッション制御プログラム |
| OSI層 | トランスポート層(4) |
| IP番号 | 6 |
| RFC(s) | 9293 |
伝送制御プロトコル( TCP ) は、インターネット プロトコル スイートの主要なプロトコルの 1 つです。これは、インターネット プロトコル(IP)を補完する初期のネットワーク実装に由来します。そのため、スイート全体は一般にTCP/IPと呼ばれます。TCP は、 IP ネットワーク経由で通信するホスト上で実行されているアプリケーション間で、オクテット(バイト)ストリームの信頼性の高い、順序付けられた、エラー チェックされた配信を提供します。ワールド ワイド ウェブ、電子メール、リモート管理、ファイル転送、ストリーミング メディアなどの主要なインターネット アプリケーションは、 TCP/IP スイートのトランスポート層の一部である TCP に依存しています。SSL /TLS は多くの場合 TCP 上で実行されます。今日でも、TCP はほとんどのインターネット通信のコア プロトコルであり、さまざまなネットワーク間で信頼性の高いデータ転送を保証しています。[ 1 ]
TCP はコネクション指向であり、送信側と受信側は合意したパラメータに基づいてまず接続を確立する必要がある。これは 3 ウェイハンドシェイク手順によって行われる。[ 2 ]接続が確立される前に、サーバーはクライアントからの接続要求を待機している (パッシブ オープン) 必要がある。3 ウェイ ハンドシェイク (アクティブ オープン)、再送、およびエラー検出によって信頼性は向上するが、待ち時間が長くなる。信頼性の高いデータ ストリームサービスを必要としないアプリケーションでは、代わりにユーザー データグラム プロトコル(UDP)を使用することもできる。UDP は、信頼性よりも時間を優先するコネクションレス型データグラムサービスを提供する。TCP はネットワーク輻輳回避を採用している。しかし、TCP には、サービス拒否、接続ハイジャック、TCP 拒否、リセット攻撃などの脆弱性がある。
| インターネットプロトコルスイート |
|---|
| アプリケーション層 |
| トランスポート層 |
| インターネット層 |
| リンク層 |
1974年5月、Vint CerfとBob Kahnは、ネットワークノード間でパケット交換を使用してリソースを共有するインターネットワーキングプロトコルを説明しました。 [ 3 ]著者は、Gérard Le Lannと協力して、フランスのCYCLADESプロジェクトの概念を新しいネットワークに取り入れていました。[ 4 ]その結果生まれたプロトコルの仕様であるRFC 675 (インターネット伝送制御プログラムの仕様) は、Vint Cerf、 Yogen Dalal、Carl Sunshineによって書かれ、1974年12月に出版されました。 [ 5 ]そこには、インターネットワークの略語として、インターネットという用語が初めて証明された使用法が含まれています。
伝送制御プログラムは、ホスト間のコネクション指向リンクとデータグラムサービスの両方を組み込んでいました。バージョン4では、モノリシックな伝送制御プログラムは、伝送制御プロトコルとインターネットプロトコルで構成されるモジュールアーキテクチャに分割されました。[ 6 ] [ 7 ]この結果、 TCP/IPと呼ばれるようになったネットワークモデルが生まれましたが、正式には国防総省インターネットアーキテクチャモデル(略してDoDモデル)やDARPAモデルなどと呼ばれていました。[ 8 ] [ 9 ] [ 10 ]後に、インターネットプロトコルスイートの一部となり、同義になりました。TCPは進化を続けており、増分更新とベストプラクティスがRFC 9293(2022)などのRFCで正式化されています。[ 11 ]
以下のインターネット実験ノート(IEN)文書はTCPの現代版への進化について説明しています。[ 12 ]
TCP は 1980 年 1 月に RFC 761 として標準化されました。
2004年、ヴィント・サーフとボブ・カーンはTCP/IPの基礎研究によりチューリング賞を受賞した。 [ 13 ] [ 14 ]
伝送制御プロトコル(TCP)は、アプリケーションプログラムとインターネットプロトコル(IP)間の中間レベルで通信サービスを提供します。インターネットモデルのトランスポート層において、ホスト間接続を提供します。アプリケーションは、リンクを介して別のホストにデータを送信するための特定のメカニズム(例えば、伝送媒体の最大伝送単位に対応するために必要なIPフラグメンテーションなど)を意識する必要はありません。トランスポート層では、TCPがすべてのハンドシェイクと伝送の詳細を処理し、通常はネットワークソケットインターフェースを介してネットワーク接続の抽象化をアプリケーションに提供します。
プロトコルスタックの下位レベルでは、ネットワークの輻輳、トラフィックの負荷分散、あるいは予測不可能なネットワーク動作などにより、IPパケットが失われたり、重複したり、順序通りに配信されなかったりすることがあります。TCPはこれらの問題を検出し、失われたデータの再送を要求し、順序が乱れたデータを並べ替え、さらにはネットワークの輻輳を最小限に抑えて他の問題の発生を抑えます。それでもデータが配信されない場合、送信元にこの失敗が通知されます。TCP受信側は、最初に送信されたオクテットのシーケンスを再構成し、それを受信側アプリケーションに渡します。このように、TCPはアプリケーションの通信を、基盤となるネットワークの詳細から 抽象化します。
TCPは、タイムリーな配信よりも正確な配信に最適化されており、順序が乱れたメッセージや失われたメッセージの再送を待つ間に、比較的長い遅延(数秒単位)が発生する可能性があります。そのため、Voice over IPなどのリアルタイムアプリケーションには特に適していません。このようなアプリケーションでは、通常、ユーザーデータグラムプロトコル(UDP)上で動作するリアルタイムトランスポートプロトコル(RTP)などのプロトコルが推奨されます。 [ 15 ]
TCPは、受信したすべてのバイトが送信したバイトと同じ順序で、かつ同一であることを保証する信頼性の高いバイトストリーム配信サービスです。多くのネットワークにおけるパケット転送は信頼性が低いため、TCPは再送を伴う肯定確認応答と呼ばれる技術を用いてこれを実現します。この技術では、受信側はデータを受信すると確認応答メッセージで応答する必要があります。送信側は送信した各パケットの記録を保持し、パケット送信時のタイマーを維持します。確認応答を受信する前にタイマーが切れた場合、送信側はパケットを再送信します。このタイマーは、パケットが失われたり破損したりした場合に備えて必要です。[ 15 ]
IP が実際のデータ配信を処理する一方で、TCP はセグメントを管理します。セグメントとは、ネットワークを効率的にルーティングするためにメッセージを分割したデータ転送の個々の単位です。たとえば、Web サーバーから HTML ファイルが送信されると、そのサーバーの TCP ソフトウェア層はファイルをセグメントに分割し、ネットワーク スタックのインターネット層に個別に転送します。インターネット層ソフトウェアは、送信先IP アドレス(およびその他のデータ) を含むヘッダーを追加することで、各 TCP セグメントを IP パケットにカプセル化します。送信先コンピューターのクライアント プログラムがそれを受信すると、トランスポート層の TCP ソフトウェアがセグメントを再構成し、ファイルの内容を受信側アプリケーションにストリーミングする際に、セグメントが正しく順序付けられ、エラーがないことを確認します。
伝送制御プロトコル(TCP)は、データストリームからデータを受け取り、それをチャンクに分割し、TCPヘッダーを追加してTCPセグメントを作成します。TCPセグメントはその後、インターネットプロトコル(IP)データグラムにカプセル化され、ピア間で交換されます。[ 16 ]
TCPパケットという用語は、非公式および公式の両方の用法で使用されていますが、より正確な用語では、セグメントはTCPプロトコルデータユニット(PDU)、データグラム[ 17 ]はIP PDU、フレームはデータリンク層PDU を指します。
プロセスはTCPを呼び出し、データバッファを引数として渡すことでデータを送信します。TCPはこれらのバッファからのデータをセグメントに分割し、インターネットモジュール(例:IP)を呼び出して各セグメントを宛先TCPに送信します。[ 18 ]
TCPセグメントは、セグメントヘッダーとデータセクションから構成されます。セグメントヘッダーには、10個の必須フィールドと、オプションの拡張フィールド(オプション、表の背景色が砂色)が含まれます。データセクションはヘッダーに続き、アプリケーションのために伝送されるペイロードデータです。[ 19 ]データセクションの長さはセグメントヘッダーでは指定されません。IPヘッダーで指定されるIPデータグラムの総長から、セグメントヘッダーとIPヘッダーの合計長を差し引くことで計算できます。
| オフセット | オクテット | 0 | 1 | 2 | 3 | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| オクテット | 少し | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
| 0 | 0 | 送信元ポート | 宛先ポート | ||||||||||||||||||||||||||||||
| 4 | 32 | シーケンス番号 | |||||||||||||||||||||||||||||||
| 8 | 64 | 確認応答番号(ACKビットがセットされている場合に意味を持つ) | |||||||||||||||||||||||||||||||
| 12 | 96 | データオフセット | 予約済み | CWR | 欧州経済委員会 | うわさ話 | 確認 | PSH | RST | シン | フィン | ウィンドウ | |||||||||||||||||||||
| 16 | 128 | チェックサム | 緊急ポインタ(URGビットがセットされているときに意味を持つ)[ 20 ] | ||||||||||||||||||||||||||||||
| 20 | 160 | (オプション) 存在する場合、データ オフセットは 5 より大きくなります。データ オフセットは 4 オクテットのワードをカウントするため、32 ビットの倍数になるようにゼロが埋め込まれます。 | |||||||||||||||||||||||||||||||
| ⋮ | ⋮ | ||||||||||||||||||||||||||||||||
| 56 | 448 | ||||||||||||||||||||||||||||||||
| 60 | 480 | データ | |||||||||||||||||||||||||||||||
| 64 | 512 | ||||||||||||||||||||||||||||||||
| ⋮ | ⋮ | ||||||||||||||||||||||||||||||||
size(Options) == (DOffset - 5) * 32[SYN]。これらは、以下に Option-Kind として示され、標準の長さは (Option-Kind, Option-Length) として示されます。| オプションの種類 | オプションの長さ | オプションデータ | 目的 | 注記 |
|---|---|---|---|---|
| 0 | 該当なし | 該当なし | オプションリストの終了 | |
| 1 | 該当なし | 該当なし | 操作なし | これを使用すると、オプション フィールドを 32 ビット境界に揃えてパフォーマンスを向上できます。 |
| 2 | 4 | SS | 最大セグメントサイズ | 詳細については、§ 最大セグメント サイズを参照してください。[SYN] |
| 3 | 3 | S | ウィンドウスケール | 詳細については、 §ウィンドウスケーリングを参照してください。[ 29 ][SYN] |
| 4 | 2 | 該当なし | 選択的確認応答が許可される | 詳細については§選択的謝辞を参照。 [ 30 ][SYN] |
| 5 | N(10、18、26、または34) | BBBB、EEEE、… | 選択的確認応答(SACK)[ 31 ] | 最初の 2 バイトの後に、選択的に確認される 1 ~ 4 個のブロックのリストが続き、32 ビットの開始/終了ポインタとして指定されます。 |
| 8 | 10 | TTTT、EEEE | タイムスタンプと前のタイムスタンプのエコー | 詳細については、 §TCPタイムスタンプを参照してください。[ 29 ] |
| 28 | 4 | 該当なし | ユーザータイムアウトオプション | RFC 5482を参照してください。 |
| 29 | 北 | 該当なし | TCP 認証オプション (TCP-AO) | メッセージ認証については、もともとBGPセッションを保護するために設計されたMD5認証(オプション19)を置き換えます。[ 32 ] RFC 5925を参照してください。 |
| 30 | 北 | 該当なし | マルチパスTCP (MPTCP) | 詳細については、マルチパス TCP を参照してください。 |

TCPプロトコルの動作は3つのフェーズに分けられます。接続確立は、データ転送フェーズに入る前に接続を確立する、複数段階のハンドシェイクプロセスです。データ転送が完了すると、接続終了によって接続が閉じられ、割り当てられたすべてのリソースが解放されます。
TCP接続は、通信のローカルエンドポイントを表すリソースであるインターネットソケットを介してオペレーティングシステムによって管理されます。TCP接続の存続期間中、ローカルエンドポイントは一連の状態変化を経験します。[ 34 ]
| 州 | 終点 | 説明 |
|---|---|---|
| 聞く | サーバ | 任意のリモート TCP エンドポイントからの接続要求を待機しています。 |
| シンセント | クライアント | 接続要求を送信した後、一致する接続要求を待機しています。 |
| SYN受信 | サーバ | 接続要求の受信と送信が完了したら、接続要求の確認応答を待機します。 |
| 設立 | サーバーとクライアント | 接続がオープン状態です。受信したデータはユーザーに配信できます。接続のデータ転送フェーズにおける通常の状態です。 |
| フィンウェイト1 | サーバーとクライアント | リモート TCP からの接続終了要求、または以前に送信された接続終了要求の確認応答を待機しています。 |
| フィンウェイト2 | サーバーとクライアント | リモート TCP からの接続終了要求を待機しています。 |
| クローズ-待機 | サーバーとクライアント | ローカル ユーザーからの接続終了要求を待機しています。 |
| 終わりに | サーバーとクライアント | リモート TCP からの接続終了要求の確認応答を待機しています。 |
| ラストACK | サーバーとクライアント | 以前にリモート TCP に送信された接続終了要求の確認応答 (その接続終了要求の確認応答を含む) を待機しています。 |
| 時間待ち | サーバーまたはクライアント | 接続上の残りのパケットの有効期限が切れたことを確認するために、十分な時間が経過するまで待機します。 |
| 閉店 | サーバーとクライアント | まったく接続状態がありません。 |
クライアントがサーバーに接続しようとする前に、サーバーはまずポートをバインドしてリッスンし、接続を待機する必要があります。これはパッシブオープンと呼ばれます。パッシブオープンが確立されると、クライアントは3ウェイ(または3ステップ)ハンドシェイクを使用してアクティブオープンを開始することで接続を確立できます。
ステップ1と2では、一方向(クライアントからサーバー)のシーケンス番号を確立し、確認応答します。ステップ2と3では、他方向(サーバーからクライアント)のシーケンス番号を確立し、確認応答します。これらのステップが完了すると、クライアントとサーバーの両方が確認応答を受信し、全二重通信が確立されます。


接続終了フェーズでは4ウェイハンドシェイクが用いられ、接続の各側は独立して終了します。一方のエンドポイントが接続の片側を停止する場合、FINパケットを送信し、もう一方のエンドポイントはACKで確認応答します。したがって、典型的な切断では、各TCPエンドポイントからFINセグメントとACKセグメントのペアが必要です。最初のFINを送信した側が最後のACKで応答した後、タイムアウトを待ってから最終的に接続を閉じます。タイムアウト中は、ローカルポートは新規接続に利用できません。この状態では、TCPクライアントはACKが転送中に失われた場合に備えて、最終確認応答をサーバーに再送信できます。タイムアウト時間は実装に依存しますが、一般的な値は30秒、1分、2分です。タイムアウト後、クライアントはCLOSED状態に入り、ローカルポートは新規接続に利用できるようになります。[ 35 ]
3ウェイハンドシェイクによって接続を終了することも可能であり、ホストAがFINを送信し、ホストBがFINとACK(2つのステップを1つにまとめたもの)で応答し、ホストAがACKで応答する。[ 36 ]
Linux [ 37 ]などの一部のオペレーティングシステムは、半二重のクローズシーケンスを実装しています。ホストが未読の受信データがまだ残っている状態で接続をアクティブに閉じる場合、ホストはFINではなくRST信号(受信データは失われます)を送信します。これにより、TCPアプリケーションはデータ損失があったことを認識できます。[ 38 ]
接続は半オープン状態になることがあります。これは、片側が接続を終了しているが、もう片側がまだ終了していない状態です。終了した側は接続にデータを送信できなくなりますが、もう片側は送信できます。終了側は、もう片側も終了するまでデータの読み取りを継続する必要があります。[ 39 ] [ 40 ]
ほとんどの実装では、セッションと実行中のオペレーティングシステムプロセスをマッピングするテーブルにエントリを割り当てます。TCPパケットにはセッション識別子が含まれていないため、両方のエンドポイントはクライアントのアドレスとポートを使用してセッションを識別します。パケットを受信するたびに、TCP実装はこのテーブルを参照して宛先プロセスを見つける必要があります。テーブルの各エントリは、伝送制御ブロック(TCB)と呼ばれます。TCBには、エンドポイント(IPとポート)、接続の状態、交換されるパケットに関する実行データ、およびデータの送受信用のバッファに関する情報が含まれています。
サーバー側のセッション数はメモリによってのみ制限され、新しい接続が到着するにつれて増加しますが、クライアントはサーバーに最初のSYNを送信する前に、一時的なポートを割り当てる必要があります。このポートは通信中ずっと割り当てられたままであり、各クライアントのIPアドレスからの送信接続数を効果的に制限します。アプリケーションが不要な接続を適切に閉じることができない場合、クライアントはリソース不足に陥り、他のアプリケーションからのTCP接続も含めて、新しい接続を確立できなくなる可能性があります。
両方のエンドポイントは、未確認パケットと受信済み(ただし未読)データ用のスペースも割り当てる必要があります。
伝送制御プロトコルは、ユーザー データグラム プロトコルと比較して、いくつかの重要な機能が異なります。
TCPは、データの各バイトを識別するためにシーケンス番号を使用します。シーケンス番号は、各コンピュータから送信されたバイトの順序を識別するため、順序が乱れた配信が発生しても、データを正しい順序で再構成することができます。最初のバイトのシーケンス番号は、最初のパケット(SYNフラグ付き)の送信側によって選択されます。この番号は任意に設定できますが、 TCPシーケンス予測攻撃を防ぐには、実際には予測不可能である必要があります。
確認応答(ACK)は、データの受信側から送信側に指定されたバイトまでのデータが受信されたことを通知するために、シーケンス番号とともに送信されます。ACKは、データがアプリケーションに配信されたことを意味するのではなく、受信側がデータの配信責任を負うようになったことを示すだけです。
信頼性は、送信側が失われたデータを検出し、再送信することで実現されます。TCPは、損失を特定するために主に2つの手法を使用します。再送信タイムアウト(RTO)と重複累積確認応答(DupAcks)です。
TCPセグメントが再送されると、元の配信試行と同じシーケンス番号が保持されます。配信順序と論理的なデータ順序の混同により、再送後に確認応答を受信した場合、送信者は元の送信に対する確認応答なのか再送に対する確認応答なのかを判断できなくなります。これはいわゆる再送の曖昧性です。[ 41 ] TCPは再送の曖昧性によって複雑さを招きます。[ 42 ]
ストリーム内の単一のセグメント(セグメント番号 100 とします)が失われた場合、受信側は累積 ACK を使用するため、そのセグメント番号 (100) を超えるパケットを確認できません。そのため、受信側は別のデータ パケットを受信すると、パケット 99 を再度確認します。この重複した確認応答は、パケット損失の信号として使用されます。つまり、送信側が重複した確認応答を 3 つ受信した場合、最後の未確認パケットを再送信します。ネットワークがセグメントの順序を入れ替えて重複した確認応答を引き起こす可能性があるため、しきい値を 3 に設定します。このしきい値により、順序入れ替えによる不要な再送信を回避できることが実証されています。[ 43 ]一部の TCP 実装では、選択的確認応答(SACK) を使用して、受信したセグメントに関する明示的なフィードバックを提供します。これにより、TCP が正しいセグメントを再送信する能力が大幅に向上します。
重複確認応答しきい値を超える順序変更がある場合、再送の曖昧さにより、誤った高速再送や輻輳回避が発生する可能性があります。[ 44 ]過去20年間で、インターネット上でパケットの順序変更がより多く観測されており[ 45 ]、LinuxカーネルなどのTCP実装では、重複確認応答しきい値を調整するためのヒューリスティックな方法を採用しています。[ 46 ]最近では、重複ACKベースの高速再送を完全に廃止し、タイマーベースのものに置き換える取り組みが行われています。[ 47 ] (以下で説明する従来のRTOと混同しないでください)。Recent Acknowledgment(RACK) [ 48 ]と呼ばれる時間ベースの損失検出アルゴリズムは、LinuxとWindowsのデフォルトのアルゴリズムとして採用されています。[ 49 ]
送信者はセグメントを送信する際、確認応答の到着時刻を控えめに見積もったタイマーを初期化する。タイマーが満了すると、セグメントは再送され、新しいタイムアウトしきい値は以前の値の2倍に設定され、指数関数的なバックオフ動作となる。通常、タイマーの初期値は平滑化されたRTT + max( G , 4 × RTT変動)であり、Gはクロック粒度である。[ 50 ]これは、中間者攻撃(DoS)などの欠陥のある、あるいは悪意のある攻撃者による過剰な送信トラフィックを防ぐ。
正確な RTT 推定は損失回復に重要であり、送信者は十分な時間が経過した後 (つまり、RTO 時間を決定した後)、確認応答のないパケットは失われたと想定できるためです。[ 51 ]再送のあいまいさにより、送信者の RTT 推定が不正確になる可能性があります。[ 51 ] RTT が可変の環境では、誤ったタイムアウトが発生する可能性があります。[ 52 ] RTT が過小評価されている場合、RTO が起動し、不要な再送とスロースタートがトリガーされます。誤った再送の後、元の送信の確認応答が到着すると、送信者はそれが再送を確認したと信じ、元の送信と再送の間に送信されたセグメントが失われたと誤って結論付け、リンクが実際に輻輳するほどの不要な再送を引き起こします。[ 53 ] [ 54 ]選択的確認応答により、この影響を軽減できます。[ 55 ] RFC 6298では、実装はRTTを推定する際に再送セグメントを使用してはならないと規定されている。[ 56 ] Karnのアルゴリズムは、 RTOを調整する前に明確な確認応答があるまで待つことで、最終的に良好なRTT推定値が生成されることを保証する。[ 57 ]しかし、誤った再送の後には、そのような明確な確認応答が到着するまでにかなりの時間がかかり、その間パフォーマンスが低下する可能性がある。[ 58 ] TCPタイムスタンプもRTOの設定における再送の曖昧性の問題を解決しますが、[ 56 ]必ずしもRTT推定値を改善するわけではありません。[ 59 ]
シーケンス番号により、受信側は重複したパケットを破棄し、順序が乱れたパケットを適切な順序に並べることができます。確認応答により、送信側は失われたパケットをいつ再送信するかを判断できます。
正確性を保証するためにチェックサムフィールドが含まれています。詳細は「チェックサムの計算」を参照してください。TCPチェックサムは現代の標準では弱いチェックであり、通常はTCPとIPの両方の下層である第2層でCRC整合性チェックと組み合わせて使用されます。これはPPPやイーサネットフレームで使用されています。しかし、CRCで保護されたホップ間でパケットにエラーが発生することはよくあり、16ビットのTCPチェックサムはこれらのエラーのほとんどを検出します。[ 60 ]
TCPは、送信側がTCP受信側で確実に受信・処理できないほど高速にデータを送信することを避けるために、エンドツーエンドのフロー制御プロトコルを使用します。フロー制御のメカニズムは、ネットワーク速度の異なるマシンが通信する環境では不可欠です。例えば、PCが受信データの処理速度が遅いスマートフォンにデータを送信する場合、スマートフォンは過負荷にならないようにデータフローを調整する必要があります。[ 15 ]
TCPはスライディングウィンドウフロー制御プロトコルを使用します。各TCPセグメントにおいて、受信側は受信ウィンドウフィールドに、接続中にバッファリング可能な追加受信データ量(バイト単位)を指定します。送信側ホストは、受信側ホストからの確認応答と受信ウィンドウの更新を待つ前に、指定されたデータ量までしか送信できません。

受信側がウィンドウサイズ0をアドバタイズすると、送信側はデータの送信を停止し、持続タイマーを開始します。持続タイマーは、受信側からの後続のウィンドウサイズ更新が失われ、送信側が受信側から新しいウィンドウサイズ更新を受信するまでデータを送信できない場合に発生する可能性のあるデッドロック状態からTCPを保護するために使用されます。持続タイマーが期限切れになると、TCP送信側は小さなパケットを送信することで回復を試みます。受信側は、新しいウィンドウサイズを含む別の確認応答を送信することで応答します。
受信側が受信データを少しずつ処理している場合、小さな受信ウィンドウを繰り返し通知することがあります。これは「シリーウィンドウ症候群」と呼ばれます。TCPヘッダーのオーバーヘッドが比較的大きいことを考えると、TCPセグメントで数バイトのデータだけを送信するのは非効率的だからです。
TCPの最後の主要な側面は輻輳制御です。TCPは、高いパフォーマンスを実現し、輻輳崩壊(ネットワークパフォーマンスが著しく低下するグリッドロック状態)を回避するために、いくつかのメカニズムを採用しています。これらのメカニズムは、ネットワークに入るデータの速度を制御し、データフローを崩壊を引き起こす速度以下に抑えます。また、フロー間の割り当てを ほぼ最大最小公平なものにします。
送信側は、送信データに対する確認応答、あるいは確認応答がないことを手がかりに、TCPの送信側と受信側間のネットワーク状況を推測します。タイマーと組み合わせることで、TCPの送信側と受信側はデータフローの動作を変更できます。これは一般的に輻輳制御または輻輳回避と呼ばれます。
現代のTCPの実装には、スロースタート、輻輳回避、高速再送、高速回復という4つの相互に関連したアルゴリズムが含まれています。[ 61 ]
さらに、送信者は、送信者と受信者の間の推定往復時間(RTT) と、この往復時間の変動に基づいた再送タイムアウト(RTO) を採用している。 [ 62 ] RTT の推定には微妙な点がある。例えば、送信者は再送パケットの RTT サンプルを計算する際には注意が必要である。通常、送信者はKarn のアルゴリズムまたは TCP タイムスタンプを使用する。[ 29 ]これらの個々の RTT サンプルはその後、時間の経過に沿って平均化され、 Jacobson のアルゴリズムを使用して平滑化された往復時間 (SRTT) が作成される。この SRTT 値が往復時間の推定値として使用される。
TCPの強化により、損失を確実に処理し、エラーを最小限に抑え、輻輳を管理し、超高速環境での高速化を実現することは、現在も研究と標準化が進められている分野です。その結果、TCP輻輳回避アルゴリズムには様々なバリエーションが存在します。
最大セグメント サイズ(MSS) は、TCP が 1 つのセグメントで受信するデータの最大量 (バイト単位) です。最高のパフォーマンスを得るには、パケット損失や過度の再送につながるIP フラグメンテーションを回避できる程度に MSS を小さく設定する必要があります。これを実現するために、通常 MSS は TCP 接続の確立時に MSS オプションを使用して各側から通知されます。オプションの値は、送信側と受信側が直接接続されているネットワークのデータ リンク層の最大転送単位(MTU) サイズから導出されます。TCP の送信側は、パス MTU 検出を使用して送信側と受信側の間のネットワーク パスに沿った最小 MTU を推測し、それを使用して MSS を動的に調整してネットワーク内の IP フラグメンテーションを回避できます。
MSSアナウンスはMSSネゴシエーションとも呼ばれますが、厳密に言えばMSSはネゴシエートされません。TCP接続では、双方向のデータフローに対して、完全に独立した2つのMSS値が許可されるため、[ 63 ] [ 18 ]、双方向接続において共通のMSS設定について合意する必要はありません。
オリジナルのTCPで採用されていた累積確認応答方式のみに依存すると、パケットが失われた際に非効率になる可能性があります。例えば、シーケンス番号1,000から10,999までのバイトが、同じサイズの10個の異なるTCPセグメントで送信され、2番目のセグメント(シーケンス番号2,000から2,999)が伝送中に失われたとします。純粋な累積確認応答プロトコルでは、受信側は累積ACK値として2,000(受信データの最後のシーケンス番号の直後のシーケンス番号)しか送信できず、3,000から10,999までのバイトを正常に受信したと判断できません。そのため、送信側はシーケンス番号2,000から始まるすべてのデータを再送しなければならない可能性があります。
この問題を緩和するために、TCP はRFC 2018で 1996 年に定義された選択的確認応答 (SACK)オプションを採用しています。これにより、受信側は、基本的な TCP 確認応答と同様に、連続して受信した最後の連続バイトの最後のシーケンス番号の直後のシーケンス番号に加えて、正しく受信した不連続なパケット ブロックを確認することができます。確認応答には複数のSACK ブロックを含めることができ、各 SACK ブロックはブロックの左端(ブロックの最初のシーケンス番号) とブロックの右端(ブロックの最後のシーケンス番号の直後のシーケンス番号) によって伝達され、ブロックは受信側が正しく受信した連続した範囲です。上記の例では、受信側は累積 ACK 値が 2,000 の ACK セグメントと、シーケンス番号 3,000 と 11,000 の SACK オプション ヘッダーを送信します。したがって、送信者は、シーケンス番号が 2,000 から 2,999 の 2 番目のセグメントのみを再送信します。
TCP送信側は、順序が乱れたセグメントの配信を損失セグメントと解釈することがあります。その場合、TCP送信側は順序が乱れたパケットの前のセグメントを再送信し、その接続におけるデータ配信速度を低下させます。この問題は、2000年5月にRFC 2883で定義されたSACKオプションの拡張である重複SACKオプションによって解決されます。TCP受信側が2つ目の重複パケットを検出すると、セグメントが損失していないことを示すD-ACKを送信し、TCP送信側はより高い伝送速度を回復できます。
SACKオプションは必須ではなく、双方がサポートしている場合にのみ機能します。これは接続確立時にネゴシエートされます。SACKはTCPヘッダーオプションを使用します(詳細は「TCPセグメント構造」を参照)。SACKの使用は広く普及しており、主要なTCPスタックはすべてSACKをサポートしています。選択的確認応答は、ストリーム制御伝送プロトコル(SCTP)でも使用されます。
選択的確認応答は「破棄」される可能性があり、この場合、受信者は選択的に確認応答されたデータを一方的に破棄します。RFC 2018ではこのような動作は推奨されていませんが、例えばバッファスペースが不足した場合などに受信者が破棄するオプションを許可するため、これを禁止していませんでした。[ 64 ]破棄の可能性は、送信者と受信者の両方にとって実装の複雑さにつながり、送信者にメモリコストを課します。[ 65 ]
高帯域幅ネットワークをより効率的に利用するために、より大きなTCPウィンドウサイズを使用できます。16ビットのTCPウィンドウサイズフィールドはデータフローを制御し、その値は65,535バイトに制限されています。サイズフィールドはこの制限を超えて拡張できないため、スケーリング係数が使用されます。RFC 1323で定義されているTCPウィンドウスケールオプションは、最大ウィンドウサイズを1ギガバイトに拡張するために使用されるオプションです。TCPチューニングには、このような大きなウィンドウサイズへのスケーリングが必要です。
ウィンドウスケールオプションは、TCP 3ウェイハンドシェイク中にのみ使用されます。ウィンドウスケール値は、16ビットのウィンドウサイズフィールドを解釈する際に左シフトするビット数を表します。ウィンドウスケール値は、各方向ごとに独立して0(シフトなし)から14まで設定できます。どちらの方向でもウィンドウスケールを有効にするには、両側ともSYNセグメントでこのオプションを送信する必要があります。
一部のルーターやパケットファイアウォールは、送信中にウィンドウスケーリング係数を書き換えます。これにより、送信側と受信側で異なるTCPウィンドウサイズが想定されます。その結果、トラフィックが不安定になり、非常に遅くなる可能性があります。この問題は、故障したルーターの背後にある一部のサイトで確認されています。[ 66 ]
1992年にRFC 1323で定義されたTCPタイムスタンプは、TCPがパケットの送信順序を判断するのに役立ちます。TCPタイムスタンプは通常、システムクロックに同期されておらず、ランダムな値から始まります。多くのオペレーティングシステムは、経過ミリ秒ごとにタイムスタンプを増分しますが、RFCでは、刻みは秒数に比例するべきであるとのみ規定されています。
タイムスタンプ フィールドは 2 つあります。
TCPタイムスタンプは、 Protection Against Wrapped Sequence Numbers(PAWS)と呼ばれるアルゴリズムで使用されます。PAWSは、受信ウィンドウがシーケンス番号のラップアラウンド境界を越えた場合に使用されます。パケットが再送された可能性がある場合、「このシーケンス番号は最初の4GBにあるか、それとも2番目の4GBにあるか」という問いに答え、タイムスタンプがその答えを決定します。
また、アイフェル検出アルゴリズムはTCPタイムスタンプを使用して、再送信がパケットの損失または順序の乱れによって発生しているかどうかを判断します。[ 67 ]
TCPタイムスタンプはLinuxではデフォルトで有効になっています[ 68 ]。Windows Server 2008、2012、2016ではデフォルトで無効になっています[ 69 ]。
最近の統計によると、Windows Server 2008以降Windows Serverがサポートを終了したため、TCPタイムスタンプの採用率は約40%で停滞しています。[ 70 ]
キューに入れられたストリームの終了を待つ代わりに、ストリームを中断または中止することができます。これは、データを緊急として指定することで行われます。これにより、送信は帯域外データ(OOB)としてマークされ、受信側プログラムに直ちに処理するように指示されます。終了すると、TCPはアプリケーションに通知し、ストリームキューを再開します。例えば、TCPをリモートログインセッションに使用する場合、ユーザーはキーボードシーケンスを送信することで、リモートで実行中のプログラムが現在の転送を完了するのを待たずに、そのプログラムを中断または中止することができます。[ 15 ]
緊急ポインタはリモートホスト上の処理を変更するだけで、ネットワーク自体の処理を高速化することはありません。この機能はシステムによって実装が異なったり、不十分であったり、サポートされていない場合もあります。この機能が利用可能な場合でも、OOBデータの1バイトのみが確実に処理されると想定するのが賢明です。[ 71 ] [ 72 ]この機能は頻繁に使用されないため、一部のプラットフォームでは十分にテストされておらず、WinNukeなどの脆弱性と関連付けられています。
通常、TCP は完全なデータ パケットを送信するまで 200 ミリ秒待機します ( Nagle アルゴリズムは小さなメッセージを 1 つのパケットにグループ化しようとします)。この待機は、ファイル転送中に頻繁に繰り返されると、小さいながらも深刻な遅延を引き起こす可能性があります。たとえば、一般的な送信ブロックは 4 KB、一般的な MSS は 1460 であるため、10 Mbit/s イーサネットでは 2 つのパケットがそれぞれ約 1.2 ミリ秒かけて送信され、その後、TCP がバッファがいっぱいになるのを待つ 197 ミリ秒の一時停止の後に、残りの 1176 を運ぶ 3 番目のパケットが送信されます。telnet の場合、ユーザーがキー入力を行うたびに、それが画面に表示される前に、サーバーによってエコー バックされます。この遅延は非常に煩わしいものになります。
ソケットオプションを設定すると、TCP_NODELAYデフォルトの200ミリ秒の送信遅延が上書きされます。アプリケーションプログラムは、このソケットオプションを使用して、文字または文字列を書き込んだ後に出力を強制的に送信します。
RFC 793ではPSH、プッシュビットは「受信TCPスタックにこのデータを受信アプリケーションに直ちに送信するように指示するメッセージ」と定義されています。 [ 15 ]バークレーソケットを使用してユーザー空間でプッシュビットを指示または制御する方法はなく、プロトコルスタックによってのみ制御されます。[ 73 ]
TCPは様々な方法で攻撃を受ける可能性があります。TCPの徹底的なセキュリティ評価の結果と、特定された問題に対する可能な緩和策は2009年に公開され[ 74 ] 、 IETF内で2012年まで検討されました[ 75 ]。注目すべき脆弱性には、サービス拒否攻撃、接続ハイジャック、TCP拒否、TCPリセット攻撃などがあります。
攻撃者は偽装IPアドレスを使用し、意図的に組み立てたSYNパケットとそれに続く多数のACKパケットを繰り返し送信することで、偽の接続を追跡するためにサーバーに大量のリソースを消費させることができます。これはSYNフラッド攻撃として知られています。この問題の解決策として提案されているものには、 SYNクッキーや暗号パズルなどがありますが、SYNクッキーには独自の脆弱性が存在します。[ 76 ] Sockstressも同様の攻撃であり、システムリソース管理によって軽減できる可能性があります。[ 77 ] TCP持続タイマーを悪用した高度なDoS攻撃は、Phrack No. 66で分析されています。[ 78 ] PUSHフラッドとACKフラッドは、他の亜種です。[ 79 ]
TCPセッションを盗聴し、パケットをリダイレクトできる攻撃者は、TCP接続をハイジャックすることができます。攻撃者は、進行中の通信からシーケンス番号を取得し、ストリーム内の次のセグメントに見せかけた偽のセグメントを偽造します。単純なハイジャックでは、片方の端末で1つのパケットが誤って受け入れられる可能性があります。受信側ホストが偽のセグメントに確認応答すると、同期が失われます。[ 80 ]ハイジャックは、攻撃者がTCP接続を恒久的に制御することを可能にするARPスプーフィングやその他のルーティング攻撃と組み合わせられる可能性があります。
RFC 1948以前は、初期シーケンス番号が容易に推測可能だったため、別の IP アドレスを偽装することは難しくありませんでした。以前の実装では、攻撃者は ARP 攻撃やルーティング攻撃による通信傍受を必要とせず、受信者が別の IP アドレスから送信されたと信じるパケットシーケンスを盲目的に送信できました。偽装された IP アドレスの正当なホストがダウンしていることを確認するか、サービス拒否攻撃によってダウン状態に陥らせるだけで十分でした。そのため、初期シーケンス番号は現在ランダムに選択されています。
次に送信するパケットの盗聴とサイズ予測が可能な攻撃者は、既存の接続を中断することなく、受信側に悪意のあるペイロードを受け入れさせることができます。攻撃者は、次に送信されると予想されるパケットのシーケンス番号とペイロードサイズを持つ悪意のあるパケットを挿入します。最終的に正当なパケットを受信すると、既に受信したパケットと同じシーケンス番号と長さであることが判明し、通常の重複パケットとして暗黙のうちに破棄されます。つまり、正当なパケットは悪意のあるパケットによって拒否されるのです。コネクションハイジャックとは異なり、接続が同期解除されることはなく、悪意のあるペイロードが受け入れられた後も通信は通常どおり継続されます。TCP拒否により、攻撃者は通信に対する制御力が低下しますが、攻撃の検出は特に困難になります。受信側が何か異常があるという唯一の証拠は、IPネットワークでは通常発生する単一の重複パケットです。拒否されたパケットの送信者は、攻撃の証拠を一切見ることができません。[ 81 ]
TCP接続は、送信元アドレス、送信元ポート、宛先アドレス、宛先ポートの4つの組によって識別されます。 [ d ] [ 82 ] [ 83 ]ポート番号は、異なるサービスを識別し、ホスト間の複数の接続を許可するために使用されます。[ 16 ] TCPは16ビットのポート番号を使用し、送信元ポートと宛先ポートのそれぞれに65,536の可能な値を提供します。[ 19 ]接続の識別がアドレスに依存するということは、TCP接続が単一のネットワークパスにバインドされていることを意味します。TCPは、マルチホームホストが利用できる他のルートを使用できず、エンドポイントのアドレスが変更されると接続が切断されます。[ 84 ]
ポート番号は、ウェルノウン、登録済み、および動的またはプライベートの 3 つの基本カテゴリに分類されます。ウェルノウン ポートは、Internet Assigned Numbers Authority (IANA) によって割り当てられ、通常、システム レベルのプロセスで使用されます。サーバーとして実行され、接続を受動的にリッスンする既知のアプリケーションは、通常、これらのポートを使用します。例としては、FTP (20 および 21)、SSH (22)、TELNET (23)、SMTP (25)、HTTP over SSL/TLS (443)、HTTP (80) などがあります。[ e ]登録済みポートは、通常、エンドユーザー アプリケーションがサーバーに接続するときに一時的なソース ポートとして使用されますが、サード パーティによって登録された名前付きサービスを識別することもできます。動的ポートまたはプライベート ポートもエンドユーザー アプリケーションで使用できますが、通常、これらのポートは特定の TCP 接続以外では意味を持ちません。
ネットワーク アドレス変換(NAT) は、通常、パブリック側で動的ポート番号を使用して、パブリック ネットワークとプライベートサブネット間を通過するトラフィックのフローを明確にし、サブネット上の多数の IP アドレス (およびそのポート) を 1 つのパブリック アドレスで処理できるようにします。
TCPは複雑なプロトコルです。長年にわたり大幅な機能強化が行われ、提案されてきましたが、最も基本的な動作は、1974年の最初の仕様RFC 675 、および1981年9月に公開されたv4仕様RFC 793以来、大きく変わっていません。1989年10月に公開されたRFC 1122では、TCPプロトコルの実装要件がいくつか明確化されました。8つの必須仕様と20を超える強く推奨される機能強化のリストは、RFC 7414で参照できます。このリストに含まれるRFC 2581(TCP輻輳制御)は、近年の最も重要なTCP関連RFCの1つであり、過度の輻輳を回避する更新されたアルゴリズムについて説明しています。2001年には、輻輳回避シグナリングメカニズムである明示的輻輳通知(ECN)について説明するRFC 3168が執筆されました。
オリジナルの TCP 輻輳回避アルゴリズムはTCP Tahoeとして知られていましたが、その後多くの代替アルゴリズムが提案されてきました ( TCP Reno、TCP Vegas、FAST TCP、TCP New Reno、TCP Hyblaなど)。
マルチパスTCP(MPTCP)[ 85 ] [ 86 ]はIETFで現在も行われている取り組みで、TCP接続で複数のパスを使用することでリソース使用率を最大化し冗長性を高めることを目的としています。無線ネットワークにおいてマルチパスTCPが提供する冗長性により、異なるネットワークを同時に使用できるようになり、スループットの向上とハンドオーバー機能の向上がもたらされます。また、マルチパスTCPはデータセンター環境においてもパフォーマンス上の利点をもたらします。[ 87 ]マルチパスTCPのリファレンス実装[ 88 ]はLinuxカーネルで開発されました。[ 89 ]マルチパスTCPはiPhone、iPad、MacのSiri音声認識アプリケーションをサポートするために使用されています。[ 90 ]
tcpcryptは、2010年7月に提案された、TCP自体にトランスポートレベルの暗号化を直接提供する拡張です。透過的に動作し、設定を一切必要としないように設計されています。TLS(SSL)とは異なり、 tcpcrypt自体は認証を提供しませんが、アプリケーションが認証を行うためのシンプルなプリミティブを提供します。tcpcryptのRFCは、2019年5月にIETFによって公開されました。[ 91 ]
TCP Fast Openは、2つのエンドポイント間の連続したTCP接続の開始を高速化するための拡張機能です。暗号化Cookieを用いて3ウェイハンドシェイクを省略することで機能します。これは、セキュリティ上の問題から広く採用されなかったT/TCPと呼ばれる以前の提案に似ています。 [ 92 ] TCP Fast Openは2014年にRFC 7413として公開されました。 [ 93 ]
2013年5月に提案された比例レート削減(PRR)は、Googleのエンジニアによって開発されたTCP拡張機能です。PRRは、回復後のTCPウィンドウサイズがスロースタートしきい値に可能な限り近づくようにします。[ 94 ]このアルゴリズムは回復速度を向上させるように設計されており、Linux 3.2以降のカーネルではデフォルトの輻輳制御アルゴリズムとなっています。[ 95 ]
TCP Cookie Transactions(TCPCT)は、2009年12月に提案された拡張機能であり[ 96 ]、サービス拒否攻撃からサーバーを保護することを目的としています。SYN Cookieとは異なり、TCPCTはウィンドウスケーリングなどの他のTCP拡張機能と競合しません。TCPCTは、サーバーが多数の短命TCP接続を処理する必要があるDNSSECの必要性から設計されました。2016年、TCPCTはTCP Fast Openに取って代わられ、廃止されました。元のRFCのステータスは歴史的に変更されました。[ 97 ]
TCPの処理能力要件を克服する一つの方法は、TCPオフロードエンジン(TOE)として広く知られるハードウェア実装を構築することです。TOEの主な問題は、コンピューティングシステムへの統合が難しく、コンピュータやデバイスのオペレーティングシステムに大幅な変更が必要になることです。
TCP低電力(TCPlp)は、UDPベースのCoAPが優先されるリソースが限られた環境で動作することが実証されています。[ 98 ] [ 99 ]
TCP のワイヤデータは、プロトコル メタデータがクリアテキストで送信されるため、経路上の観察者に重要な情報収集および変更の機会を提供します。[ 100 ] [ 101 ]この透明性はネットワーク オペレータ[ 102 ]や研究者[ 103 ]には有用ですが、プロトコル メタデータから収集された情報によってエンド ユーザのプライバシーが低下する可能性があります。[ 104 ]メタデータのこの可視性と柔軟性により、TCP の拡張が困難になっています。これはプロトコルの骨化の一例であり、任意の中間ノード (「ミドルボックス」) がそのメタデータに基づいて決定を下したり、メタデータを変更したりできるため、[ 105 ] [ 106 ]エンドツーエンドの原則が破られています。[ 107 ]ある測定によると、インターネット上のパスの 3 分の 1 が TCP メタデータを変更する少なくとも 1 つの仲介者に遭遇し、パスの 6.5% が仲介者からの有害な骨化の影響を受けています。[ 108 ]中継者による拡張性ハザードを回避することはMPTCPの設計に大きな制約を課し、[ 109 ] [ 110 ]中継者によって生じる困難はウェブブラウザへの TCP Fast Open の導入を妨げてきた。[ 111 ]もう一つの骨化の原因は、エンドポイント、典型的にはオペレーティングシステムカーネル[ 112 ]またはTCP オフロードエンジンを備えたハードウェアにおけるTCP 機能の変更の難しさである。[ 113 ]
TCP は信頼性の高いバイト ストリームの抽象化をアプリケーションに提供するため、行頭ブロッキングの影響を受ける可能性があります。つまり、パケットの順序が変わったり失われたりして再送が必要になった場合 (つまり順序が変わった場合)、ストリームの後のほうのデータが、前のほうのデータの受信前に受信されることがあります。ただし、後のデータは通常、前のデータが受信されるまで使用できないため、ネットワーク レイテンシが発生します。複数の独立した上位レベルのメッセージがカプセル化され、単一の TCP 接続に多重化されている場合、行頭ブロッキングにより、後に送信され完全に受信されたメッセージの処理が、前に送信されたメッセージの配信を待つことになる可能性があります。[ 114 ] Web ブラウザは、複数の並列接続を開くことで行頭ブロッキングを軽減しようとします。これにより、接続を繰り返し確立するコストが発生するだけでなく、エンドポイントでそれらの接続を追跡するために必要なリソースも増加します。[ 115 ]並列接続では、情報をまとめて監視し、観測されたネットワーク状況に迅速に対応するのではなく、互いに独立して動作する輻輳制御も備えている。[ 116 ] TCPの積極的な初期送信パターンは、複数の並列接続が開かれた場合に輻輳を引き起こす可能性がある。また、接続ごとの公平性モデルは、このアプローチを採用するアプリケーションによるリソースの独占につながる。[ 117 ]
ウェブユーザーが経験する遅延の主な要因は、接続の確立である。[ 118 ] [ 119 ] TCP の 3 ウェイ ハンドシェイクでは、データを送信する前に接続を確立する際に 1 RTT の遅延が発生する。[ 119 ]フローが短い場合、これらの遅延は極めて重大である。[ 120 ]トランスポート層セキュリティ(TLS) では、接続確立時に鍵交換のために独自のハンドシェイクが必要である。階層化設計のため、TCP ハンドシェイクと TLS ハンドシェイクは順番に進行し、TCP ハンドシェイクが完了するまで TLS ハンドシェイクは開始できない。[ 121 ] TCP 経由のTLS 1.2で接続を確立するには 2 RTT が必要である。[ 122 ] TLS 1.3では、状況によってはゼロ RTT の接続再開が可能だが、TCP 上に階層化されている場合は、TCP ハンドシェイクに 1 RTT が必要であり、これでは初期接続を支援できない。ゼロRTTハンドシェイクは、効率的でリプレイセーフかつ前方セキュアな非対話型鍵交換が未解決の研究課題であるため、暗号技術上の課題も提示している。[ 123 ] TCPファストオープンは、初期(SYNおよびSYN-ACK)パケットでデータの送信を許可し、接続確立時の遅延を1RTT削減する。[ 124 ]しかし、TCPファストオープンはプロトコルの骨化のために導入が困難であり、2020年時点で、これをデフォルトとして使用しているWebブラウザはない。 [ 111 ]
TCPスループットはパケットの並べ替えの影響を受けます。並べ替えられたパケットは重複した確認応答の送信を引き起こし、それが閾値を超えると、不要な再送と輻輳制御を引き起こします。また、範囲の先頭で並べ替えられたパケットを受信すると、広い範囲が一度に確認応答されるため、送信動作がバースト的になることもあります(ヘッドオブラインブロッキングがアプリケーションに与える影響に似ています)。[ 125 ] Blanton & Allman (2002)は、スループットは並べ替えの量と反比例関係にあり、ある閾値を超えるとすべての並べ替えが不要な再送を引き起こすことを発見しました。[ 126 ]並べ替えの軽減は、送信者が不要な再送を送信したことを判断できるかどうか、つまり再送の曖昧さを解消できるかどうかに依存します。 [ 127 ]並べ替えによって引き起こされる不要な再送を減らすと、真の損失からの回復が遅れる可能性があります。[ 128 ]
選択的確認応答はスループットに大きなメリットをもたらす可能性があり、Bruyeron、Hemon、Zhang (1998)は最大45%の向上を測定した。[ 129 ]この改善の重要な要因は、選択的確認応答によって損失後のスロースタートを回避できる頻度が高くなり、利用可能な帯域幅をより有効に活用できることである。[ 130 ]しかし、TCPは最大3つのシーケンス番号ブロックしか選択的に確認応答できない。これにより再送速度が制限され、損失回復が困難になったり、特に損失が大きい環境では不必要な再送が発生したりする可能性がある。[ 131 ] [ 132 ]
TCP は元々、パケット損失がネットワーク輻輳の結果であると考えられ、予防措置として輻輳ウィンドウ サイズが大幅に削減される有線ネットワーク用に設計されたものです。しかし、無線リンクでは、フェーディング、シャドウイング、ハンドオフ、干渉、およびその他の無線の影響 (厳密には輻輳ではない) により、散発的で通常は一時的な損失が発生することが知られています。無線パケット損失による輻輳ウィンドウ サイズの (誤った) バックオフ後、輻輳回避フェーズでウィンドウ サイズが控えめに削減される場合があります。これにより、無線リンクが十分に活用されなくなります。これらの有害な影響に対抗するための広範な研究が行われてきました。提案されているソリューションは、クライアントまたはサーバーでの変更を必要とするエンドツーエンド ソリューション、[ 133 ]セルラー ネットワークの無線リンク プロトコルなどのリンク層ソリューション、またはエンド ノードを変更せずにネットワークに何らかの変更を必要とするプロキシベースのソリューションに分類できます。[ 133 ] [ 134 ]無線問題を解決するために、 Vegas、Westwood、Veno、Santa Cruz などの代替輻輳制御アルゴリズムが提案されている。
TCPアクセラレータの考え方は、ネットワークプロセッサ内でTCP接続を終端し、データをエンドシステムへの2番目の接続に中継することです。送信元から発信されたデータパケットはアクセラレータノードでバッファリングされ、アクセラレータノードはパケット損失が発生した場合にローカル再送信を実行します。これにより、パケット損失が発生した場合、送信元と受信元間のフィードバックループがアクセラレータノードと受信元間のフィードバックループに短縮され、受信側へのデータ配信速度が向上します。[ 135 ]
TCPはレート適応型プロトコルであるため、TCP送信側がネットワークにパケットを投入するレートは、ネットワーク内の現在の負荷状態と受信側の処理能力に正比例します。ネットワーク内の現在の負荷状態は、送信側が受信した確認応答に基づいて判断されます。アクセラレーションノードは、送信側と受信側の間のフィードバックループを分割することで、パケットあたりのラウンドトリップ時間(RTT)の短縮を保証します。RTTが短いほど、ネットワークの変化への応答時間が短縮され、送信側がこれらの変化に迅速に対応できるようになるため、メリットがあります。
この方法の欠点は、TCPセッションをアクセラレータ経由で送信する必要があることです。つまり、ルーティングが変更され、アクセラレータがパス上に存在しなくなると、接続が切断されます。また、TCP ACKメカニズムのエンドツーエンド特性も損なわれます。つまり、送信側がACKを受信しても、パケットはアクセラレータによって保存されており、受信側には配信されていないのです。
パケットスニファーは、ネットワークリンク上のTCPトラフィックを傍受し、リンクを通過するパケットをエンジニアに表示することで、ネットワーク、ネットワークスタック、およびTCPを使用するアプリケーションのデバッグに役立ちます。一部のネットワークスタックはSO_DEBUGソケットオプションをサポートしており、setsockoptを使用してソケットで有効にすることができます。このオプションは、そのソケット上のすべてのパケット、TCP状態、およびイベントをダンプするため、デバッグに役立ちます。Netstatもデバッグに使用できるユーティリティです。
多くのアプリケーションでは、TCPは適切ではありません。アプリケーションは通常、失われたパケットの再送信コピーを受信するまで、失われたパケットの後に続くパケットにアクセスできません。これは、ストリーミングメディア、リアルタイムマルチプレイヤーゲーム、Voice over IP (VoIP) などのリアルタイムアプリケーションでは問題を引き起こします。これらのアプリケーションでは、すべてのデータを順番に取得するよりも、ほとんどのデータをタイムリーに取得する方が一般的に有用です。
歴史的およびパフォーマンス上の理由から、ほとんどのストレージエリアネットワーク(SAN)は、ファイバーチャネル接続を介してファイバーチャネルプロトコル(FCP)を使用しています。組み込みシステム、ネットワークブート、そして多数のクライアントからの単純なリクエストを処理するサーバー(DNSサーバーなど)では、TCPの複雑さが問題となる場合があります。NAT (STUNなどのシステムを使用)の背後にある2つのホスト間でデータを転送するようなトリックは、TCPのような比較的複雑なプロトコルを介さずに実行できるため、はるかに簡単です。
一般的に、TCPが適さない場合は、ユーザーデータグラムプロトコル(UDP)が使用されます。UDPは、TCPと同じアプリケーション多重化とチェックサムを提供しますが、ストリームや再送は処理しません。そのため、アプリケーション開発者は状況に応じて適切な方法でコーディングしたり、前方誤り訂正やエラー隠蔽などの他の方法に置き換えたりすることができます。
ストリーム制御伝送プロトコル(SCTP)は、TCPに類似した信頼性の高いストリーム指向サービスを提供するプロトコルです。TCPよりも新しく、かなり複雑なため、まだ広く普及していません。しかし、信頼性と準リアルタイム性が重視される状況での使用を目的として設計されています。
Venturi トランスポート プロトコル (VTP) は、ワイヤレス データ転送に関連する非効率性を克服するために TCP を透過的に置き換えるように設計された 特許取得済みの独自プロトコルです。
TCP輻輳回避アルゴリズムは、データの送信元が事前に分からないアドホック環境では非常に有効に機能します。環境が予測可能な場合は、非同期転送モード(ATM)などのタイミングベースのプロトコルを使用することで、TCPの再送オーバーヘッドを回避できます。
UDPベースのデータ転送プロトコル(UDT)は、帯域幅遅延積が大きいネットワークではTCPよりも効率と公平性に優れています。[ 136 ]
多目的トランザクション プロトコル(MTP/IP) は、さまざまなネットワーク状況、特に TCP が非効率であると認識される状況で、高いスループットとトランザクション パフォーマンスを適応的に実現するように設計された特許取得済みの独自ソフトウェアです。
TCPがIPv4上で動作する場合、チェックサムを計算する方法は次のように定義されます。[ 18 ]
チェックサムフィールドは、ヘッダーとテキストに含まれるすべての16ビットワードの1の補数の合計の1の補数です。チェックサム計算では、合計するデータの16ビットアライメントを確保する必要があります。セグメントに含まれるヘッダーとテキストのオクテットの数が奇数の場合、最後のオクテットの右側にゼロをパディングしてチェックサム用の16ビットワードを形成することで、アライメントを実現できます。パディングはセグメントの一部として送信されません。チェックサムの計算中、チェックサムフィールド自体はゼロに置き換えられます。
つまり、適切なパディングの後、すべての16ビットワードが1の補数演算を用いて加算されます。そして、その合計がビットごとに補数化され、チェックサムフィールドとして挿入されます。チェックサム計算に使用されるIPv4パケットヘッダーを模倣した疑似ヘッダーは次のとおりです。
| オフセット | オクテット | 0 | 1 | 2 | 3 | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| オクテット | 少し | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
| 0 | 0 | 送信元アドレス | |||||||||||||||||||||||||||||||
| 4 | 32 | 宛先アドレス | |||||||||||||||||||||||||||||||
| 8 | 64 | ゼロ | プロトコル (6) | TCP 長さ | |||||||||||||||||||||||||||||
| 12 | 96 | 送信元ポート | 宛先ポート | ||||||||||||||||||||||||||||||
| 16 | 128 | シーケンス番号 | |||||||||||||||||||||||||||||||
| 20 | 160 | 確認番号 | |||||||||||||||||||||||||||||||
| 24 | 192 | データオフセット | 予約済み | 旗 | ウィンドウ | ||||||||||||||||||||||||||||
| 28 | 224 | チェックサム | 緊急ポインタ | ||||||||||||||||||||||||||||||
| 32 | 256 | (オプション) | |||||||||||||||||||||||||||||||
| 36 | 288 | データ | |||||||||||||||||||||||||||||||
| 40 | 320 | ||||||||||||||||||||||||||||||||
| ⋮ | ⋮ | ||||||||||||||||||||||||||||||||
チェックサムは次のフィールドで計算されます。
TCPがIPv6上で動作する場合、チェックサムを計算する方法が変更されます。[ 137 ]
チェックサム計算に IP ヘッダーのアドレスを含めるトランスポートまたはその他の上位層プロトコルは、IPv6 で使用するために、32 ビットの IPv4 アドレスではなく 128 ビットの IPv6 アドレスを含めるように変更する必要があります。
チェックサムの計算のために IPv6 ヘッダーを模倣した疑似ヘッダーを以下に示します。
| オフセット | オクテット | 0 | 1 | 2 | 3 | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| オクテット | 少し | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
| 0 | 0 | 送信元アドレス | |||||||||||||||||||||||||||||||
| 4 | 32 | ||||||||||||||||||||||||||||||||
| 8 | 64 | ||||||||||||||||||||||||||||||||
| 12 | 96 | ||||||||||||||||||||||||||||||||
| 16 | 128 | 宛先アドレス | |||||||||||||||||||||||||||||||
| 20 | 160 | ||||||||||||||||||||||||||||||||
| 24 | 192 | ||||||||||||||||||||||||||||||||
| 28 | 224 | ||||||||||||||||||||||||||||||||
| 32 | 256 | TCP 長さ | |||||||||||||||||||||||||||||||
| 36 | 288 | ゼロ | 次のヘッダー (6) | ||||||||||||||||||||||||||||||
| 40 | 320 | 送信元ポート | 宛先ポート | ||||||||||||||||||||||||||||||
| 44 | 352 | シーケンス番号 | |||||||||||||||||||||||||||||||
| 48 | 384 | 確認番号 | |||||||||||||||||||||||||||||||
| 52 | 416 | データオフセット | 予約済み | 旗 | ウィンドウ | ||||||||||||||||||||||||||||
| 56 | 448 | チェックサム | 緊急ポインタ | ||||||||||||||||||||||||||||||
| 60 | 480 | (オプション) | |||||||||||||||||||||||||||||||
| 64 | 512 | データ | |||||||||||||||||||||||||||||||
| 68 | 544 | ||||||||||||||||||||||||||||||||
| ⋮ | ⋮ | ||||||||||||||||||||||||||||||||
チェックサムは次のフィールドで計算されます。
Zeroes == 0多くのTCP/IPソフトウェアスタック実装では、ネットワークへの送信前、またはネットワークからの受信時に検証のためにネットワークアダプタ内でハードウェア支援を利用してチェックサムを自動計算するオプションが提供されています。これにより、チェックサム計算に伴うCPU負荷が軽減され、ネットワーク全体のパフォーマンスが向上する可能性があります。
この機能により、チェックサムオフロードの使用を認識しない、または不確実なパケットアナライザが、ネットワークアダプタにまだ到達していない送信パケットに無効なチェックサムを報告する可能性があります。 [ 138 ]これは、ネットワークアダプタによって送信される前に傍受されたパケットに対してのみ発生します。ネットワークアダプタによって回線上で送信されるすべてのパケットには有効なチェックサムが含まれます。[ 139 ]この問題は、同じホスト上の仮想マシン間で送信されるパケットを監視するときにも発生する可能性があります。この場合、仮想デバイスドライバは、チェックサムが後で VM ホストカーネルまたはその物理ハードウェアによって計算されることがわかっているため、最適化としてチェックサムの計算を省略する可能性があります。
階層化の原則に違反することで、インターネットプロトコルの設計は失敗に終わります。具体的には、TCPを2つの目的で使用しようとしています。1つはホストレベルのエンドツーエンドプロトコルとして機能させること、もう1つはインターネットパッケージングおよびルーティングプロトコルとして機能することです。これら2つの機能は、階層化されモジュール化された方法で提供されるべきです。
{{cite book}}: CS1 メンテナンス: 場所の発行元が見つかりません (リンク)は、ネットワークアダプタに送信される前のパケットをキャプチャします。チェックサムはまだ計算されていないため、正しいチェックサムは表示されません。さらに悪いことに、ほとんどのOSはこのデータを初期化しないため、本来表示されるべきではないメモリの小さなチャンクが表示される可能性があります。Wireshark 1.2以降の新規インストールでは、IP、TCP、UDPのチェックサム検証がデフォルトで無効になっています。必要に応じて、各解析ツールのチェックサム検証を手動で無効にすることができます。
チェックサムオフロードは、送信するネットワークパケットが実際にチェックサムを計算する前にWiresharkに渡されるため、しばしば混乱を引き起こします。Wiresharkはこれらの「空の」チェックサムを取得し、無効として表示しますが、パケットがネットワークハードウェアから送信される際には有効なチェックサムが含まれているにもかかわらずです。