TCP
Transmission Controll Protocol
データが正しく伝送されることはIPデータグラムでは保証されていない。信頼性のある通信を実現するためのトランスポート層のプロトコル。
特徴
Pros
- 伝送中のエラーによるパケットの欠落時の再送処理
- 送信したパケットの順番保証
- 双方向通信のサポート
- ストリームでの通信
- UDPではデータグラム単位のため、送信データの組み立てや、受信後のデータの組み立てなど検討する必要がある。
- TCPでは、任意の長さのバイト列として受信できる
- パケットの分割や受信後の組み立てはTCPが実装されたネットワークソフトで管理されるため煩雑な手順が不要
- フロー制御
- 相手の処理能力に合わせて通信量が過大にならないように調整するフロー制御をもっている
Cons
- 3 way hand shakeは1往復分のレイテンシが発生
- スロースタートはすべての新規接続で発生
- スループットは現在の輻輳ウインドウサイズで制限される
パフォーマンス
- サーバーのカーネルのバージョンアップ
- cwndサイズを10に設定(RFC6928で推奨)
- アイドル後のスロースタートの無効化
- ウインドウスケーリングの有効化
- 不要なデータ送信を削除
- 送信データを圧縮
- 物理的にサーバーをユーザーの近くにし、ラウンドトリップを削減
- 既存のTCP接続の再利用
TCPセグメント
TCPのデータ伝送は、IPデータグラムにおさめておこなわれる。この個々のパケットのことをTCPセグメントと呼び、TCPヘッダとデータ部で構成される。
フラグメントされずに送信できるセグメントの最大サイズのことをMSSと呼ぶ。(イーサネットでは1460バイト)
- フラグ
- 通信を制御する情報。各ビットごとにフラグがきまっており、TCPの状態が設定されている
- SYN, ACK,FINなど…
- フラグは複数同時に建てることができるヨ
- 通信を制御する情報。各ビットごとにフラグがきまっており、TCPの状態が設定されている
- シーケンス番号
- 受信側がデータの連続性や欠落の有無の確認する情報
- コネクション確立時に初期値が決まり、送信データのサイズ分(バイト単位)増えていく
- 確認応答などでも加算される
- 確認応答番号
- ACKフラグがセットされたセグメントの確認応答番号には、次に受信すべきシーケンス番号が設定されている。
- 現在のシーケンス番号は初期値からわかってるので、受信したデータサイズから計算して次のシーケンス番号がわかる
- これは確認応答番号より前のデータは受信できたことを送信側に通知する番号
- コネクションが確立した後は、すべてのセグメントでACKがセットされているので、常に確認応答番号が設定されている
- 最大値(32bit)を超えた場合、0に戻る
- 「受信ウインドウサイズ」というパラメータで確認応答なしに一度に受け取れるデータ量を定められる
- ACKフラグがセットされたセグメントの確認応答番号には、次に受信すべきシーケンス番号が設定されている。
- ウインドウサイズ(rwnd)
- 受信できるバッファの空きサイズ
- データの送信側がACK時のこの空きサイズをみてバッファを溢れさせないように送信量を判断する
- 16bitしかないので、「ウインドウスケール」オプションで2のべき乗倍のサイズにスケールできる
データの伝送
- コネクションの確立
- コネクションのクローズ
- 片方のホストが突然ダウンなどで接続が切れた場合、クローズ処理がおこなわれない
- この場合、生きているホスト側のコネクションが残り続ける
- キープアライブを有効にするとデータの送受信がなくなったコネクションで、空のTCPセグメントが送信される
- 複数回ACKが返ってこない状態が続いたら、コネクションを強制的にクローズする
- コネクションの状態
スロースタート
データ受信側の容量を超過しないために調整させる仕組みの1つ。
ACKを受け取るごとにサーバー側がcwndのセグメント(=MSS)を指数関数的に増加させることで必要なウインドウサイズに調整していく。
- 輻輳ウインドウサイズ(cwnd)
- データ送信側がACKを受け取る前に続けて送信できるデータ量
- rwndとcwndの小さい方が適用される
- 初期設定は控えめな設定値(linuxはinitcwnd)
- 最大は輻輳しきい値を超えるか、パケロスが発生し輻輳回避アルゴリズムが制御する
- スロースタートリスタート(SSR)
- TCPの接続が一定時間アイドル状態だった場合、ネットワークの状態に変化がある可能性を考えて輻輳ウインドウサイズは初期化される
- HTTPキープアライブのような長期間アイドルが発生するような接続の場合、パフォーマンス影響が大きい場合、サーバー側のSSRを無効にすることが推奨されている
輻輳回避
パケロスが発生するということは、ネットワークのどこかでパケットを捨てる必要があるほど混雑している。
これ以上のパケロスが発生しないようにウインドウサイズを調整することでパケロスを抑える。輻輳ウインドウサイズがリセットされると輻輳回避アルゴリズムはパケロスを最小化するためのウインドウサイズ拡大アルゴリズムを指定する。
帯域幅遅延積
リンク容量とエンドツーエンドの遅延の積。任意の時点における送信中未応答のデータの最大量。
送信か受信のどちらかが頻繁に停止して、送信したパケットに対するACKを待つ必要がある場合、接続の最大スループットが制限される。遅延なく送信するためには、データの送受信を継続できるほどウインドウサイズを十分に大きくする必要があるため、ウインドウサイズはパケットの往復時間に依存している。
エラーの対応
- 送信データの欠落
- 送信したセグメントがロストした場合、送信側は一定時間内にACKされなかったら再送する
- 途中のデータが欠落
- 複数のセグメントを送信したのに、ACKに含まれる確認応答番号が増えていない場合
- 3回同じ確認応答番号のACKが返却された場合、確認応答番号以降のデータを再送する
- 3回待つのは、受信した順序が入れ替わった場合も一時的に同じ状態になるため
- 重送
- 受信済みのデータを再送されて再び受信した場合
- 欠落したセグメントの再送や、ACKが欠落した場合に発生する可能性がある
- 受信側はデータは破棄するが、ACKは送信する
バッファ管理
TCPがデータを送信するとき、まずプログラムからTCPの管理している送信バッファに書き込まれる。書き込まれたデータはOS側が非同期的にネットワークに送信していく。
受信側は反対にネットワークから受信したデータをOSがTCPが管理する受信バッファに書き込んでいく。
受信バッファに書き込まれたデータを読み出して受信プログラムに渡している。
スライディングウインドウ
TCPの再送処理などをするために複雑なバッファ管理が必要になる。このバッファ管理方法として伝送する一連のバイト列データの一部をスライドする窓でのぞくような形でバッファリングする手法。
⇛概要説明:TCP - 通信効率の向上 ( ウィンドウ制御 )
HoL(Head of line)ブロッキング
アプリケーションがバッファからデータを読み込むには必要なデータが揃うまで待機する必要がある。また、アプリケーションがソケットのバッファからデータを読み込むとき、TCPは単に伝送遅延と認識し、これをHoLブロッキングと呼ぶ。
サーバーの複数のコネクションの実現
Webサーバーなどは1つのウェルノウンポートで複数のコネクションを実現している。これは、クライアント側のソケットアドレスと組み合わせることで一意に識別している。
TCP Fast Open
最初のSYNパケットでアプリケーションのデータ送信を開始できる。