TCPの制御(フロー制御・ウィンドウサイズ)

 TCPによる通信では、送信側がセグメントを送信し、そのセグメントを受信側が受信すると必ずACKの応答を返すようになっています。

 受信側の応答には、期待する次のシーケンス番号(受信したセグメントのシーケンス番号+1)を返します。

つまり、

今までの分は、ちゃんと受信できているので、次のセグメントを送って下さい。

という意味になります。

 TCPにおけるフロー制御は、ウィンドウサイズで実現しています。ウィンドウサイズによって一度に送信できるセグメントの数が決まります。TCPでは、一度に送受信するセグメントの数をコントロールすることで、フロー制御を行っています。

 もう少し、詳しく説明すると、ウィンドウサイズは、通信相手のバッファ量を指します。受け取ったデータは、一時的にバッファに溜められます。

データ転送が早いと、すぐにバッファは一杯になり、溢れ出してしまいます。そして、パケットは破棄されることになります。

つまり、ウィンドウサイズまでのデータは、一度に送っても相手はオーバフローしないことになります。

 TCPの通信では、スリーウェイハンドシェイクのコネクションの確立時に、シーケンス番号、確認応答番号の他に、ウィンドウサイズ(自分のバッファのサイズ)やMSSもお互いに教え合っています。

 この教えられたウィンドウサイズとMSSから、一度に送信できるセグメント数を求めることができます。TCPでは、一度に送受信するセグメントの数をコントロールすることで、フロー制御を行っています。

まずは、一度に送ることが可能なセグメント数が「1」の時のフロー制御を説明して行きます。

例えば

ウィンドウサイズ = 1,000
MSS = 1,000

の場合、一度に送ることが可能なセグメント数は、「1」になります。

 上図を見れば分かるように、1セグメントを送信する度に、確認応答を行っています。個々のパケットに対してACKの応答を待ってからでないと、次のセグメントを送信できません。

これだと、確かに確実に相手に届けることができますが、手間がかかりすぎてオーバヘッドが高くなってしまいます。

もっと、効率よく送信しないと時間がかかり過ぎてしまいます。

 効率よく送信するには、個々のセグメントの対するACKの応答を待ってから次のセグメントを送信するのではなく、ACKの応答を待たないで一度に複数のセグメントが送信できるようになっています。

スライディングウィンドウ

ここでは、一度に複数のセグメントを送信する場合におけるやり取りの流れを説明して行きます。

 スリーウェイハンドシェイクのコネクションの確立時には、シーケンス番号、確認応答番号の他にウィンドウサイズ(自分のバッファのサイズ)やMSSもお互いに教え合っています。

例えば、受信側のウィンドウサイズとMSSの値が以下の場合

ウィンドウサイズ = 3,000
MSS = 1,000

一度に送ることが可能なセグメント数は、「3」になります。

 送信側が、セグメントの1、2、3を連続して送信しています。送信側は、パケット3の応答の「ACK=4」を受信すると、今度は、連続してセグメントの4、5、6を連続して送信します。
※実際には、受信側が報告してくるウィンドウサイズで変わります。

 個々のセグメントの対するACKの応答を待ってから、次のセグメントを送信するのではなく、一度に複数のセグメントが送信することで効率性を高めています。このようにTCPにおける通信では、ACKの応答を待つことなく一度に複数のセグメント送信することで、フロー制御を行っています。

 一度に送信できるセグメント数は、ウィンドウサイズによって決まります。このウィンドウサイズは、いつも同じ値というわけではありません。相手先のバッファサイズによって増減します。

 受信側のバッファサイズは、セグメントを受信すると小さくなりますし、処理が完了すると空き容量が増えてバッファサイズが大きくなります。

 送信側は、次に、どのセグメントをどれぐらいの数で送信すればよいのかを管理する必要があります。そうしなければ、たくさんのセグメントを送信して受信側のバッファをあふれさせてしまいかねませんし、逆に送信するセグメント数が少なすぎると効率が悪くなってしまうからです。

 そこで、TCPでは、次にどのセグメントをどれぐらい送信すればよいのかということを管理するためにスライディングウィンドウという仕組みを使っています。