■ TCPおさらい・ふたたび
さて、まだまだTCPの話は続く。
今日は「ウィンドウ」の話だ。
うぃんどう。
OSのことですか?
いや、あれはウィンドウ「ズ」だからな。
今回のものはTCP内部での「窓」だ。
はぁ。
まず、TCPヘッダのおさらいからいこう。
送信元ポート番号(16) | 宛先ポート番号(16) | ||
シーケンス番号(32) | |||
確認応答番号(32) | |||
データオフセット(4) | 予約(6) | 制御ビット(6) | ウィンドウ(16) |
チェックサム(16) | 緊急ポインタ(16) | ||
オプション |
[Table39-01:TCPヘッダ]
ちゃんと「ウィンドウ」という項目がある。
今回は、このウィンドウとシーケンス番号と確認応答番号の3つを使って説明していく。
シーケンス番号と確認応答番号は前回でてきましたよね。
え〜っと。大きなデータを分割して届ける際に使う番号でしたね。
うむ。
シーケンス番号は、送るデータの先頭バイトの番号だ。
確認応答番号は受け取った際に返す確認応答につける次の送られてくる(予定の)データの先頭バイトの番号でした。
うむうむ、そうだ。
では、1回のデータ転送で送るデータ量のことをなんといったかね?
え〜。
MSSでしたよね。分割したものがセグメント。
うむ。
これはTCPのデータ受け渡しが開始されるスリーウェイハンドシェイクで決定される。
でした。
つまり一連の流れは、以下の図のようになる。
[Figure40-05:シーケンス・確認応答の流れ]
確実・正確に送ると。
そうだ。それがTCPの謳い文句だからな。
だが、その「確実・正確」のための技術はこれだけではない。
これだけじゃない?
なんかもう、十分な気がするんですけど。
■ ウィンドウサイズ
まず。前回やった、「セグメント送信 → 確認応答」という流れだが。
これは手間がかかりすぎる。
手間がかかりすぎるって。
それはそうですけど、「正確・確実」なためには必要なものなんでしょう?
うむ。
それはそうなのだが。実際はもうちょっと効率のよい送り方をしないと、時間だけがかかりすぎる。
はぁ。
「セグメント送信 → 確認応答」という流れは一緒だが。
「複数のセグメント転送 → 確認応答」という形にする。そうすれば、時間的にだいぶ効率がよくなる。
[Figure41-01:効率のよい送り方]
このように、左の方式に比べると、同じ3つのセグメントを送るにも右の方式はだいぶ時間的に短縮できる。
複数のセグメント送信?
セグメント送信とACKが入れ違いになってますけど。
前回で説明したのは「ACKで受信を確認したら次のセグメント」という方式だったわけだ。
これを「ACKを待たずに複数のセグメントを送る」方式にしたわけだ。
ええぇ? でもそれだと、「確実・正確」の謳い文句がおかしくなってしまいませんか?
一気に送って、後々になって届かなかったことがわかってしまう、とか。
うむ、その可能性はある。
なので、「確実・正確」に、かつ効率よく送るためにTCPはウィンドウ制御というものを行う。
うぃんどう制御。
窓の制御?
何故「ウィンドウ」という名前がついたかは、後で話そう。
まず、前にバッファというものを話したよな。
第38回で出てきた奴ですか?
受け取ったデータを一時的に保管しておく場所でしたっけ?
そうだ。
送られてきたデータはバッファに溜め置かれて、そこから処理される。
処理よりも、データ転送が早いとバッファに溜まっていって、あふれ出ちゃうんでしたよね。
うむ。TCPではこのあふれ出る(オーバフロー)を防がなければならない。データの損失だからな。
なので、相手に自分がどれだけのバッファ量を持つかを教える必要がある。
ははぁ、さすがTCP。
きめ細かいですね。
このサイズのことをウィンドウサイズという。
うぃんどうさいず。
これは、MSSと同じように、スリーウェイハンドシェイクで初期値を決定する。
[Figure41-02:ウィンドウサイズの決定]
シーケンス番号、確認応答番号やMSSと一緒に相手に教えるんですね。
■ ウィンドウ制御
ウィンドウサイズは、相手のバッファの量だ。
つまり、ウィンドウサイズまでのデータは一度に送っても相手はオーバフローしないということがわかるわけだ。
えっと、そう、なるのかな?
なるのだ。
つまり、ウィンドウサイズとは確認応答を待たずに送ることのできるデータ量ということになる。
相手がオーバフローしないのと、確認応答を待たなくってよいってのは別問題ではないんですか?
確認応答は「受け取りました」という意味だろう? 相手のウィンドウサイズを知ることは「受け取れなかった原因」の1つであるオーバフローの可能性を失くすわけだから、確認応答なしでもいいことになる。
「受け取れなかった原因」の「1つ」。
他にも受け取れなかった原因はあるんですよね。その場合はどうするんですか?
うむ。それはちゃんと後で説明する。
とりあえず、ウィンドウ制御を説明しよう。
[Figure41-03:ウィンドウ制御]
はわ〜。
「枠」には「現在送信中で確認応答が返ってきていないもの」が入る。
この枠は順々に下に下がっていくわけだ。
「再送されることがないので、枠からはずします」っていうのは?
うむ。「確認応答が届いた」=「相手にそのセグメントは届いた」だろう?
なのでもう送る必要がないので、送っているものが入る「枠」からはずすのだよ。
ははぁ。
このように、「枠(ウィンドウ)」が「ずれる(スライド)」ので、この方式をスライディングウィンドウ方式という。
すらいでぃんぐうぃんどう。
スライドするウィンドウですか。
もうちょっとわかりやすく、簡略化したものを見てもらったほうがいいかな。
[Figure41-04:スライディングウィンドウ]
あ〜、なるほど。
送るデータ全体のうち、今送信中のデータだけが見える窓(ウィンドウ)なわけですか。
そうだ。だからウィンドウと呼ばれる。
これがスライドするから、スライディングウィンドウ、だな。
ははぁ、なるほど。
■ ウィンドウ制御・エラーの場合
しかし、上の例は非常に上手くいった場合なわけだ。
処理速度が速くて、いつもバッファは空なわけだからな。
そうですね。いつもウィンドウサイズ=3000ですからね。
では、バッファが埋まっていった場合の例を出そう。
[Figure41-05:バッファがたまった場合]
ははぁ。なかなか見事なものですねぇ。
うむ。相手のバッファのサイズに合わせるのだ。
絶対にバッファフローを起こさせないためにな。
フロー制御って言うんでしたよね。
うむうむ。その通り。
さて、次は転送中のエラーの場合を考えてみよう。
[Figure41-06:転送中のエラーの場合]
はわ〜。
基本は、確認応答が返ってこなかったら再送するだ。
え〜っと。
でも同じ確認応答が3回きても再送するんですね。
うむ。途中のセグメントが抜けた場合、そうなる。
前のセグメントが来ないのに、後のセグメントばかり来るからな。
「いいから、前のやつをよこせ」と何度も確認応答を送りつけるわけですね。
でも、なんで3回なんですか?
ううむ。これを説明しだすと長いのだが。
簡単に言えば、「2回では再送が多発しすぎる。4回では無駄が多くなりすぎる」からだ。
ははぁ。
もう1つ覚えておいて欲しいのは。
バッファ内の並べ替えだ。
え〜っと、例では。1001〜2000が来なかったため、2001以降のセグメントがあっても処理を保留してましたよね。
それで1001〜2000のセグメントがきたら、並べ替えた、と。
そうだ。
TCPでは必ず番号順に処理を行う。これはセグメントが届かなかった場合以外でも起きうる。
そうなんですか?
[Figure41-07:セグメントの遅延]
途中の回線での遅延などにより、先に送ったものが後につく場合もあるのだよ。
よって、この場合もバッファ内の並べ替えを行って、番号順に処理を行う。
ははぁ。
しかし、こうしてみると、TCPってしっかりとした作りになってるんですねぇ。
そうだな。
何度も言うように、正確・確実だからな。
ですね。
さて、まだまだTCPには、正確・確実に送るための制御がある。
まだあるんですか。
うむ、それは長いから次回にするが。
輻輳制御というやつだ。
…?
なんて読むんですか、それ?
ふふふ。それは次回のお楽しみという奴にしておこう。
う〜、気になるぅ〜。
3分間ネットワーキングでした〜♪
- ウィンドウサイズ
- [window size]
- オーバフロー
-
[over flow]
- スライディングウィンドウ
- [sliding window]
- ネット君の今日のポイント
-
- TCPはウィンドウ制御というもので、バッファフローを防ぐ。
- 相手のバッファサイズ=ウィンドウサイズを確かめつつ送受信を行う。
- ウィンドウサイズの分までは確認応答を受信しなくても一度に送れる。
- 相手のウィンドウサイズによって、送るセグメントを変えていく。この方式をスライディングウィンドウという。
- 受け取った順ではなく、シーケンス番号順に処理を行うため、処理を保留したり並べ替えたりする。