Windows における TCP の再送機能を確認する

サーバー側と通信中に途中経路上で問題が発生するなどしてパケットをロストした場合、UDPであれば単純にそのパケットは失われる。TCPであれば再送機能が動作して、ある程度の期間の通信経路断(ケーブルが抜けるとか)は乗り越えてくれるはず。それ故にTCPなのだから。

今回は『ある程度の期間』とか『はず』というところを実際に検証してみた。この検証を行うきっかけになったものの関係で Windows Server 2008 R2 をクライアント側にし、Telnetクライアント側からTelnetサーバー側へのパケット通信を再送させる。

再送機能を制御しているパラメータ

TcpMaxDataRetransmissions

TCP通信において、パケットの再送を何回行うかを制御しているパラメータ。デフォルトは 5 であり、5回再送することになっている。

検証1 (デフォルト状態)

TcpMaxDataRetransmissions

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters に TcpMaxDataRetransmissions は定義されていないため、デフォルトの5が使われるべき。

検証内容

telnet 通信の確立後、数回 [ENTER] キーを入力して反応があることを確認。その後サーバー側のファイアウォールを有効にして telnet 通信ポート(23)を塞ぐ。そうしてから再度クライアント側で [ENTER] キーを入力する。このときの通信を Wireshark でパケットキャプチャして観察する。

検証結果


時系列(秒時点) 動作 前回送信からの経過時間(秒) 初回送信からの経過時間(秒)
41.812 [ENTER]入力によるデータ送信(初回) 0.000 0.000
42.150 1回目の再送 (TCP Retransmission) 0.338 0.338
42.821 2回目の再送 (TCP Retransmission) 0.671 1.009
44.147 3回目の再送 (TCP Retransmission) 1.326 2.335
46.799 4回目の再送 (TCP Retransmission) 2.652 4.987
52.088 5回目の再送 (TCP Retransmission) 5.289 10.276
62.649 TCPリセット送信(クローズ) 10.561 20.837
結果評価
  • 1回目の再送までの時間はラウンド・トリップ・タイム(RTT)をベースにして計算されるため、今回は 0.338(秒) が RTT だった。
  • n回目の再送は『前回送信からの経過時間』が RTT × 2n-1 に一致。再送時間が倍々になっていくという実装が確認できた。
  • TCPの接続が切られるのは5回目の再送がタイムアウトしたと判断されるタイミングであり、(許可されていれば)6回目の再送を行うタイミングである(今回は[ENTER]入力の20.837秒後)。
  • TCPの接続が切られるまでの累積時間は RTT × (20 + 21 + 22 + 23 + 24 + 25) = RTT × (26 - 1) になる。TcpMaxDataRetransmissions を使用して次の式で表せる。

RTT × (2TcpMaxDataRetransmissions + 1 - 1)

  • 実際のところは最後の再送までに経路回復しなければ通信の維持は困難だと考えると、経路ダウンの許容時間は最後の再送までの累積時間(最後の再送のタイムアウト時間を除く)であり、次の式になる。

RTT × (2TcpMaxDataRetransmissions - 1)


検証2 (TcpMaxDataRetransmissions を 7 に変更)

TcpMaxDataRetransmissions

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters に TcpMaxDataRetransmissions を明示的に定義した。

検証内容

検証1と同様。

検証結果


時系列(秒時点) 動作 前回送信からの経過時間(秒) 初回送信からの経過時間(秒)
36.131 [ENTER]入力によるデータ送信(初回) 0.000 0.000
36.472 1回目の再送 (TCP Retransmission) 0.341 0.341
37.174 2回目の再送 (TCP Retransmission) 0.702 1.043
38.593 3回目の再送 (TCP Retransmission) 1.419 2.462
41.402 4回目の再送 (TCP Retransmission) 2.809 5.271
47.018 5回目の再送 (TCP Retransmission) 5.616 10.887
58.234 6回目の再送 (TCP Retransmission) 11.216 22.103
80.636 7回目の再送 (TCP Retransmission) 22.402 44.505
125.439 TCPリセット送信(クローズ) 44.803 89.308
結果評価
  • 再送回数は確かに5回から7回に増えた。
  • それ以外については検証1で確認できたことと同じ。
追加検証

6回目の再送から7回目の再送が行われるまでの間にサーバ側のファイアウォールを再度無効にし、telnet 通信ポート(23) を開放した。この場合は 7 回目の再送にサーバ側が応答し、通信を継続できた。