myesn

myEsn2E9

hi
github

[未完成] 4.13 ネットワークケーブルを抜いた後、元のTCP接続は存在しますか?

ネットワークケーブルを数秒抜いて再度差し込むと、元の TCP 接続は存在しますか?

一部の学生は、ネットワークケーブルが抜かれたことは物理層が切断されたことを意味するため、トランスポート層も切断されるべきであり、したがって元の TCP 接続は存在しないと言うかもしれません。有線電話をかける場合、片方の電話線が抜かれると、その通話は完全に切断されます。

しかし、このような認識は間違っています。上記の論理の問題は、ネットワークケーブルを抜くという行為がトランスポート層に影響を与えると誤って考えていることにありますが、実際には影響を与えません。

実際には、TCP 接続は Linux カーネル内でstruct socketという名前の構造体として表され、この構造体には TCP 接続の状態などの情報が含まれています。ネットワークケーブルを抜いた場合、オペレーティングシステムはこの構造体の内容を変更しませんので、TCP 接続の状態も変わりません。

例えば、ssh を使用してリモートサーバーと TCP 接続を確立し、ローカルネットワークを切断するシナリオをシミュレートすることができます。そして、以下のコマンドを使用して TCP 接続の状態を確認すると、まだ ESTABLISHED の状態であることがわかります。

# linux
# netstat: https://wangchujiang.com/linux-command/c/netstat.html
# or ss: https://wangchujiang.com/linux-command/c/ss.html
#
# grep: https://wangchujiang.com/linux-command/c/grep.html
sudo netstat -anp tcp | grep tcp | grep [dst_ip]

# windows 
# netstat: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/netstat
# or TCPView: https://learn.microsoft.com/en-us/sysinternals/downloads/tcpview
#
# findstr: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/findstr
netstat -anp tcp | findstr [dst_ip]

今、私たちはネットワークケーブルを抜いた行為が TCP 接続の状態に影響を与えないことを知っています。重要なのは、ネットワークケーブルを抜いた後、両者がどのような行動をとるかです。この問題については、ネットワークケーブルを抜いた後、データの転送があるかどうかによって場合分けする必要があります。

ネットワークケーブルを抜いた後、データの転送がある場合#

クライアントがネットワークケーブルを抜いた後、サーバーからクライアントに送信されるデータパケットは何の応答も得られず、一定時間待った後、サーバーはタイムアウト再送信メカニズムをトリガーし、応答のないデータパケットを再送信します。

サーバーがデータを再送信している間に、クライアントがちょうどネットワークケーブルを差し込んだ場合、ネットワークケーブルを抜いてもクライアントの TCP 接続の状態は変わらず、まだ ESTABLISHED の状態にあるため、クライアントは正常にサーバーから送信されたデータパケットを受け取ることができ、その後クライアントは ACK 応答パケットを返します。この時点で、クライアントとサーバーの TCP 接続はまだ存在しており、何も起こったかのように感じられます。

しかし、サーバーがデータを再送信している間に、クライアントがネットワークケーブルを差し込まない場合、サーバーのタイムアウト再送信回数が一定の閾値に達すると、カーネルはその TCP に問題があると判断し、ソケットインタフェースを介してアプリケーションにその TCP 接続の問題を通知します。その結果、サーバーの TCP 接続は切断されます。そして、クライアントがネットワークケーブルを差し込んだ後、クライアントがサーバーにデータを送信した場合、サーバーはもうクライアントと同じ四元組の TCP 接続を持っていないため、サーバーのカーネルは RST パケットを返信し、クライアントはその TCP 接続を解放します。この時点で、クライアントとサーバーの TCP 接続はすでに切断されています。

Q:TCP データパケットは具体的に何回再送信されますか?
A:Linux システムでは、TCP 接続が確立された状態でのタイムアウト再送信の最大回数を制御するために、tcp_retries2 という設定項目(/proc/sys/net/ipv4/tcp_retries2)が提供されています。デフォルト値は 15 であり、このカーネルパラメータは、TCP 接続がタイムアウト再送信を通知するためにアプリケーションに通知するまでの時間を制御します。

ただし、tcp_retries2 が 15 回設定されているからといって、TCP がタイムアウト再送信を 15 回行ってからアプリケーションに TCP 接続を終了する通知を送るわけではありません。カーネルは tcp_retries2 で設定された値に基づいて、タイムアウト(tcp_retries2 = 15 の場合、計算されるタイムアウトは 924600 ミリ秒です)を計算し、再送信間隔がこのタイムアウトを超える場合は閾値を超えたと判断し、TCP 接続を切断します。

タイムアウト再送信のプロセスでは、各ラウンドのタイムアウト時間(RTO)が指数関数的に増加します。たとえば、最初のラウンドの RTO が 200 ミリ秒であれば、2 番目のラウンドの RTO は 400 ミリ秒、3 番目のラウンドの RTO は 800 ミリ秒となります。

RTO は RTT(ラウンドトリップタイム)に基づいて計算されます。RTT が大きいほど、計算される RTO も大きくなりますので、いくつかのラウンドの再送信後、すぐに上記のタイムアウト値に達します。

例えば、tcp_retries2 が 15 回設定されている場合、計算されるタイムアウトは 924600 ミリ秒であり、再送信の合計間隔がタイムアウトに達すると再送信が停止され、TCP 接続が切断されます。

  • RTT が比較的小さい場合、初期の RTO は下限の約 200 ミリ秒に近くなります。つまり、最初のラウンドのタイムアウト時間は 200 ミリ秒であり、タイムアウトの合計時間が 924600 ミリ秒になると、15 回の再送信が行われ、タイムアウト値を超えて切断されます。
  • RTT が比較的大きい場合、初期の RTO が 1000 ミリ秒と計算されると仮定します。つまり、最初のラウンドのタイムアウト時間は 1 秒ですが、15 回の再送信は必要ありません。再送信の合計間隔は 924600 ミリ秒を超えます。

最小の RTO と最大の RTO は Linux カーネルで定義されています:

#define TCP_RTO_MAX ((unsigned)(120*HZ))
#define TCP_RTO_MIN ((unsigned)(HZ/5))

Linux 2.6 以降では、1000 ミリ秒の HZ が使用されているため、TCP_RTO_MINは約 200 ミリ秒、TCP_RTO_MAXは約 120 秒です。

tcp_retries が 15 回に設定されている場合、RTT が比較的小さい場合、初期の RTO は下限の約 200 ミリ秒に近くなります。したがって、通知が上位レイヤー(つまりアプリケーション)に切断された TCP 接続を通知するのに 924.6 秒かかります。各ラウンドの RTO の増加関係は次の表に示します:
image

ネットワークケーブルを抜いた後、データの転送がない場合#

ネットワークケーブルを抜いた後、データの転送がない場合、TCP keepalive メカニズム(TCP キープアライブメカニズム)が有効になっているかどうかによります。

TCP keepalive メカニズムが有効になっていない場合、クライアントがネットワークケーブルを抜いた後、両者がデータの転送を行わない場合、クライアントとサーバーの TCP 接続は常に存在し続けます。

一方、TCP keepalive メカニズムが有効になっている場合、クライアントがネットワークケーブルを抜いた後、両者がデータの転送を行わない場合でも、一定時間経過後、TCP は探索パケットを送信します。

参考文献#

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。