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

TCP のフロー制御の実装

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

「規定の量」とは、TCP synもしくはsyn/ack時に、自身が受信できる量を相手に通知します。具体的には「Window」Fieldとオプションの「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 の勉強については、以下の書籍がお薦めです。

シェアする

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

フォローする