TCPのフロー制御と輻輳制御とその違い 〜スライディング ウィンドウ サイズ, スロースタート, AIMD〜

TCP のフロー制御の実装

TCP ではデータ(セグメント)を受信したことを ACK で相手に知らせますが、TCP セグメントを受信するたびに ACK を返していては効率が悪いので、TCP では、規定の量の TCP セグメントを受信するまで ACK を返さなくてよい、ということになっています。その仕組みをWindowと呼びます。

「規定の量」とは、TCP SYN もしくは SYN/ACK 時に、自身が受信できる量を相手に通知します。具体的には「Window」フィールドとオプションの「Window Scale」で決定されます。

例えば「Window:Ox2000=8192Byte=8KB」、「Window Scale:Ox08=2^8=256倍」だった場合、8KB*256=2MB となります。

この場合、2MB のデータを受け取るまで、ACK を返さなくてもよいのです。なお、これらの数値は自身の「受信バッファ」の懐具合で自ら決定します。

まずはこの初期値でデータ送受信を開始しますが、データ受信をするたびに、受信処理できるバッファが減っていきます。その状況をリアルタイムで伝えるのがスライディング Windowです。

スライディング Window

スライディング Window は、自身のバッファの懐具合をリアルタイムで相手に伝える仕組みで、フロー制御の実装になります。最初に決定した Window の規定量から、TCP セグメントを受信して処理中のために使用中のバッファを差し引いた値を、同じく「Window」フィールドを使って相手に伝えます。

その Window フィールドを受信した相手はまたそれに応じたデータ分を、ACK 無しに送ることができます。このような動作により、通信を効率化します。

ただし、これはあくまで、ホストの受信バッファがこれだけある、という、ホストだけの都合であることに注意して下さい。

TCP の輻輳制御の実装

スロースタートアルゴリズム

前回の例で、いきなり 2MB 分送ると(ホストではなく)ネットワークのキャパシティオーバーになってしまう可能性があります。そうなるとまた効率が悪いので、ネットワークの都合も考える必要があります。スロースタートはネットワークの都合を考慮した輻輳制御の実装です。RFC5681 で定義されています。

このアルゴリズムを管理するパラメータとして以下2つがあります。共に単位は Byte です。

  1. Congestion Window (CW)
  2. Slow Start Threshold (SST)

CW は基本的に MSS の整数倍です。初期値/MSS の数だけパケットを送信し、送信データが SST の値に達するまで倍に増やしていきます。

閾値を超えたら輻輳を検知するまで、数パケットずつ増やしていき、輻輳を検知した場合は CW は初期値に戻り、SST は RTO 発生直前の CW の半分にセットされます。

このように『増やすときは数パケットずつ足し算、減らすときは掛け算』という方式を "Additive-Increase, Multiplicative-Decrease (AIMD)" と呼び、RFC2861 に記述されています。

なお、輻輳の検知方法としては2つあり、1つは RTO の時間が経っても ACK が返されない場合、もう1つは RTO 内だが Dup ACK によりパケットロスが検知された場合です。

なお、Windows10 では、CW の初期値は10*MSS になったようです。(Windows8.1までは 4*MSS)

TCP/UDP の勉強については、以下の書籍がお薦めです。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする