[IP1:PORT1] でリッスンする TCP サーバーを作成し、[IP2] を使用してクライアント経由で接続しました。クライアントとサーバーの両方で、次の構成値を使用してSO_KEEPALIVEおよびTCP_USER_TIMEOUTを有効にします。
TCP_KEEPIDLE = 1
TCP_KEEPINTVL = 1
TCP_KEEPCNT = 4
TCP_USER_TIMEOUT = 5000
私がキャプチャしたTCPdumpで次のことを確認しました。
- 最初は、クライアントとサーバー間で3回のハンドシェイク(syn-synack-ack)が発生します。
- 1秒ごとに、クライアントとサーバーはKeepaliveパケットを生成し、そのピアはそれに応答してackを送信します。
すべてが私が期待どおりに正確に起こっています。ただし、次のコマンドを使用してサーバーIP(IP1)を削除しました。
/sbin/ip addr del IP1 dev DEV
IPを除去した後、追跡で以下を観察した。
Keepaliveパケットは、両方のエンティティ(クライアントとサーバー)で送信され続けます。驚くべきことに、プライマリIPが削除されたにもかかわらず、サーバーはまだ接続維持パケットを送信します!
クライアントは、承認によってサーバーによって送信された Keepalive パケットに応答します。
サーバーは、クライアントが送信した Keepalive パケットの承認を送信しません。
約4秒後、サーバーIP(IP1)はクライアントに[RST、ACK]を送信し、パケット交換は発生しなくなります。
だから私は上記の2つを理解していません。
- サーバーIPが削除されても一定期間通信が続くのはなぜですか?
- サーバーがクライアントに保留パケットを送信できますが、クライアントに保守確認を送信できないのはなぜですか。
オペレーティングシステム:Red Hat Enterprise Linuxバージョン8.3
ベストアンサー1
答えは非常に曖昧ですが、これは正しい方向でより多くの調査をすることができます。
TCP 接続が確立されると、カーネルは接続のデータ構造を確立します。インターフェイスからIPアドレスを削除しても、必ずしもこの情報が完全に削除されるわけではありません。 (誰もこれを気にしないと思うので、通常はすべてのサーバーがIPアドレスを削除する前にシャットダウンされ、最終的にはクリーンアップされます。)
したがって、これらの内部データ構造は明らかに接続保持交換を実行し、いくつかのイベントが発生し(おそらく接続が切断されたと見なされるため)、接続状態全体が収集されるまでACKパケットは生成または転送されません。
詳細を知りたい場合は、カーネルコードを読み、どのデータ構造が構築されているかを調べ、IPアドレスが削除されるとどの構造が削除され、どの構造が維持されるかを調べてください。
しかし、すべてが学問的です。実際の結果がない極端な行動を見つけることができます。