(O+P)ut

OutPut Log by SE in SIer



(O+P)ut

Output Log by SE

【TCP/IP】ACKが受信に成功したセグメント番号までを返す理由

スポンサーリンク

はじめに

TCPの世界ではコネクション型でデータを伝送しますが、逐次ACKの確認を待っていると通信のスループットが落ちてしまいます。よって「スライディングウィンドウ」という考え方で応答前にデータを連続して送付します。

この仕組みにおいて、一部伝送に失敗した場合は再送制御が必要です。その際のポイントとして「受信側は最後に受信に成功したデータのACKを返す」というものがあるのですが、本記事では「なぜ一連のデータとして受信成功したものを返すのだろう?」という素朴な疑問を持たれた方向けの解説記事です。

再送制御技術

正常ケース

まずは正常に通信ができているケースを見ます。
送信側が1,2,3,4を連続して送付し、受信側は全て受信に成功します。そして、最後に受信したセグメント番号を順々に返していきます。それに対して送信側も全て応答のACKを確認しました。

送信側 セグメント# 通信の向き ACK# 受信側
1
2
3
4
5
1
2
3
4
5

3番目の受信に失敗したケース

受信側が3番目のデータが受信できなかった場合、以下のようにACKを返します。

送信側 セグメント# 通信の向き ACK# 受信側
1
2
3 ×
4
5
1
2
2
2

これによって送信側は「3」の受信に失敗したことがわかります。が、「2」をわざわざ返し続ける必要があるのでしょうか?

逆に以下のように受信に成功したものを返すとすれば

送信側 セグメント# 通信の向き ACK# 受信側
1
2
3 ×
4
5
1
2
4
5

同じように「3」の送信に失敗したことを送信側が把握できるようにも思えます。

なぜこのような仕組みなのでしょうか?

結論:送信側が受信に失敗した際に無駄な再送を行わなくて済む

送信側が3番目のデータの応答を確認できなかった場合、以下のようになります。

送信側 セグメント# 通信の向き ACK# 受信側
1
2
3
4
5
1
2
× 3
4
5

ここで送信側はデータを再送する必要がありません。受信側はデータを「5」まで確認したことが分かります。というのも、もし受信側がデータを受信できていなかったとしたらACKの応答に「5」が入ることはありません。どこかで失敗していれば最後に受信した「1」や「2」や「3」を返し続けてくるからです。

逆に例に挙げたように受信すればとりあえず返すような仕組みであれば

送信側 セグメント# 通信の向き ACK# 受信側
1
2
3 ×
4
5
1
2
×
4
5

送信側は相手が受信に成功したのかどうか、自分が応答を確認できなかっただけなのか切り分けができないため、再送する必要がでてきます。


終わりに

ACKが後続に成功したデータは無視して受信に成功したセグメント番号までを返す理由は「ACKが喪失した場合の再送を不要にするため」です。
初めてこの仕組みを見た時、よくできているものだと感心したことを覚えています。

どうようの仕組みは別のケースにも応用できると思いますので、頭の片隅に入れておくとどこかで役立つかもしれません。
以上、TCPの再送制御に関する解説記事でした。


他の記事を読む