最終的にSRTT値がRTTの推算に使われる。TCPを拡張して、喪失を高信頼に扱ったり、誤りを最小化したり、輻輳を制御してより高速化しようという試みが今も行われている。最大セグメントサイズ以下の小さなパケットをばらばらと送るのは非効率なので、送信を遅延し、それらを1つのTCPパケットにまとめるのが、Nagleアルゴリズムである。同様に、複数のACKを1つにまとめるのが、TCP遅延ACKである。どちらも、送信を遅延させるという点においては同じだが、相互に影響し合い、遅延が増大するという問題があり、詳細はNagleアルゴリズムを参照。バイト単位で指定され、単一のセグメントとして受信可能な最大データ量を示す。性能を最大限発揮するにはIPフラグメンテーションを十分防げる程度に小さくする必要がある。IPフラグメンテーションが行われると、パケット喪失時の再送に時間がかかることになる。導出したMSSを通知すればよい。送信側は経路MTU探索を使うことができ、通信相手との間にある経路でMTUが最小の部分を推定し、それを使ってMSSを動的に調整しIPフラグメンテーションを防ぐことができる。MSS通知は「MSSネゴシエーション」とも呼ばれる。ネゴシエーションというと送信側と受信側が交渉して合意に達するかのように思われるが、実際には異なり、送信する方向によってそれぞれ異なるMSSが設定可能である[15]。これは例えば一方がメモリ容量が小さいため、バッファ領域を大きくとれない場合などに起きる(発見したパスMTUより小さいこともありうる)。選択確認応答[編集]もともとのTCPプロトコルで採用されている累積確認応答方式を使うと、パケットを喪失したときに非効率になる可能性がある。10,000バイトのデータを10個のTCPセグメントで送信し、その最初のパケットが喪失したとする。累積確認応答プロトコルでは、受信側は1,000から9,999までのバイトは受信成功、ただし0から999までのバイトを含む先頭パケットの受信に失敗したという風に伝えることができないので、送信側は10,000バイト全体を再送しなければならない。(SACK)」オプションが追加された。これは、通常の累積確認応答とは別に、受信側が不連続なブロックを正しく受信したという確認応答を返せるようにしたものである。選択確認応答にはオプション部分にいくつかのSACKブロックを指定し、SACKブロックには正しく受信できた連続な範囲のシーケンス番号の開始点と終了点を指定する。シーケンス番号をSACKオプションで示せばよい。バイトを含む最初のパケットだけを再送する。パケットの順序がばらばらになると、送信側への確認応答も順序どおりにならないため送信側でパケット喪失と勘違いし、喪失したと思われるパケットを再送することがあり、同時にネットワーク輻輳を防ぐため送信ペースを落とす。オプションで再送パケットが重複していることを通知すれば、遅くなっていた送信ペースを元に戻すことができる。SACKオプションは必須ではなく、両者がサポートしている場合だけ使われる。これはコネクション確立時に調整される。SACKオプションは主なTCPスタックでサポートされており、広く使われている。ウィンドウスケーリング[編集]広帯域ネットワークをより効率的に使うには、TCPウィンドウのサイズを大きくする必要がある。TCPヘッダのウィンドウサイズのフィールドは16ビットで、2バイトから65,535バイトまでしか設定できない。ウィンドウサイズ・フィールドは拡張できないので、スケールファクタ(英語版)が導入されている。ギガバイトに拡張できる。ウィンドウスケール・オプションは3ウェイ・ハンドシェイクの際にしか使われない。ウィンドウスケール・オプションのオプション値は、16ビットのウィンドウサイズ・フィールドの値を左にシフトするビット数を表している。ウィンドウスケールの値は0(シフトしない)から14まで指定でき、通信の双方向で別々に設定できる。どちらの方向もSYNセグメントのオプションとして通知する。一部のルーターやファイアウォールは、このスケールファクタを転送時に書き換えることがある。すると送信側と受信側でウィンドウサイズの認識が異なることになり、トラフィックが不安定になって、非常に低速になることがある[16]。定義されており、パケット送出の順序をTCPレベルで知ることが出来る。TCPタイムスタンプはシステムクロックに合わせているわけではなく、無作為な値から開始する。多くのOSはこのタイムスタンプ値をミリ秒単位でインクリメントする。RFCは単に時間経過に比例して増加すべきだとしているだけである。タイムスタンプのフィールドは2つある。PAWSは、2の32乗まであるシーケンス番号が一周してしまう場合に使われる。シーケンス番号はデータバイト毎に振られるので、最大4ギガバイトしか表せないが、最近の高速ネットワークでは1分以内に一周する可能性があり、再送が必要になったとき、現在の周回なのか前の周回なのかを識別するのにタイムスタンプを使う。2.2節では、ウィンドウサイズは1ギガバイトまでとされているため、多くの実装でスケールオプションの最大値を14までとしている。TCPタイムスタンプを使っており、再送の原因がパケット喪失なのか順序がばらばらになったせいなのかを判断する。帯域外データ[編集]ストリームが完了するのを待たずに、キューイングされたストリームに割り込むことができる。指定したデータを使う。それによって受信側プログラムが緊急データをすぐさま処理すべきであることを知らせる。その処理が終了すると、もとのストリーム・キューの処理を再開する。リモートログインのセッションにTCPを使っているとき、ユーザーが実行中のプログラムをアボートさせるキーシーケンスを送るときなどに使われる。プログラムが暴走したときなど、そのプログラムの出力を待っているのではなく、強引にアボートさせたいときに必須となる[2]。帯域外データの概念は現在のインターネット向けの設計ではない。緊急ポインタは相手ホストでの処理を変えるものであって、ネットワーク上の処理は何も変わらない。緊急ポインタのあるセグメントがリモートホストに到着したとき、若干異なる2つのプロトコルの解釈があり、単一バイトの帯域外データしか信頼できないという状況になっている。溜まるか、200ミリ秒経過するまで待つ(Nagleアルゴリズムで小さいメッセージを単一パケットにまとめようとするため)。これは例えばファイル転送のような一定の送信が要求される場合に問題となることがある。送信ブロックが一般的な4KBで、MSSも一般的な1460バイトだとする。すると1ブロックが3セグメントで送信され、最後の1セグメントはMSSに満たないことになる。すると、2パケットまでは約1.2ミリ秒で送信され、1176バイトの3パケット目は197ミリ秒待ってから送信ということになる。Telnetの場合、ユーザーがキーを押下するたびに通信先からエコーバックされて画面に文字が表示される。すると、1文字押下するたびに200ミリ秒待たされることになり、非常にストレスになる。使ってデフォルトの200ミリ秒の送信遅延を変更することができる。フラグを使って「受信側TCPスタックでそのデータを即座にアプリケーションに送る」という機能が定義されている[2]。ソケットにはこれを制御するインタフェースがなく、プロトコルスタックの実装に任されている[19]。コネクション終了[編集]コネクション終了フェーズは多くの場合「4ウェイ・ハンドシェイク」を使い、コネクションの双方がそれぞれ独立に終了できる。一方がコネクションを終了したい場合、FINセグメントを送信し、相手がそのACKを返す。相手も同様にFINを送ってACKを受信することでコネクションを終了する。両方のFIN/ACK交換が済むと、最後にACKを送った側(先にFINを送った側)がタイマを設定してタイムアウトするまで当該ポートを別のコネクションに再利用できないようにする。これによって配送が遅れていたパケットが新たなコネクションで受信されて混乱するのを防ぐ。コネクションは「ハーフオープン」という状態にもでき、一方だけ終了していても、もう一方はデータを送り続けることができる。終了した側はもう一方が終了するまで受信可能の状態を継続する。応答し、ホストAがACK応答する[20]。実際にはこれが最も一般的である。両方から同時にFINセグメントを送りあい、双方がACKを返すということもありうる。FIN/ACKシーケンスが並行して行われるため、2ウェイ・ハンドシェイクと呼ぶこともできる。脆弱性[編集]TCPは様々な方法で攻撃される可能性がある。TCPの完全なセキュリティアセスメントの結果は、認識されていた問題の考えうる対策と共に2009年に公表され[21]、その後もIETF内で進められている[22]。DoS攻撃[編集]IPスプーフィングを使い、悪意を持って作ったSYNパケットを繰り返し送信することで、偽の接続に対処するために対象サーバの多大な量のリソースを消費させることができる。