サーバープロセスとクライアントプロセスが同じLinuxマシンで実行されています。
場合によっては、クライアントをkill -9
すると、tcpdump
でFIN, ACK
メッセージが送信されることがわかります。もちろん、死んだクライアントはSIGKILL
で残忍に死んでいるので、それはできませんでした。したがって、Linux OSが接続のクローズを処理すると思います。
時々、connection-close-handlingが表示されず、接続が「確立」されたままになります(netstat
による)。
Linux ubuntu 4.4.0-53-generic
で接続が閉じられるのをいつも見ています。
ときどきLinux 3.13.11
(Ubuntuではなく純粋なカーネル)で接続が閉じられているのがわかります。
私の質問は:
SIGKILL
?close()
を呼び出さない場合3.13.11
と4.4.0
の間で変更されましたか? Ubuntuには何かありますか?keepalive
ソケットオプションを知っています。Linuxが実際に接続のクローズを処理する場合。なぜそれらが存在するのですか?FIN, ACK
パケットがドロップする場合のみ?幅広い質問。おそらく、特定のカーネルバージョン間のカーネルTCPスタックについての質問を誰かが検討する可能性があります。
いくつかの一般的な答え:
SIGKILL
シグナルが発生すると、カーネルはプログラムの実行を終了し、とりわけ、プロセスの開いているファイル記述子を閉じます。 TCPソケットは、フラッシュされ、TCPシャットダウンプロセスを実行する必要があるという点で、カーネルによって通常のファイルとは少し異なって処理されます。
クライアントからの即時の「FIN、ACK」と長いソケットのシャットダウンの違いは、クライアントアプリケーションが終了したときにクライアントTCP接続がどのような状態であったかによって異なります。しかし、一般的にカーネルはアプリケーションの開いているソケットを閉じます。
サーバーは、クライアントがいつ切断するかを常に認識しているわけではありません。クライアントがハングアップしたかどうかを確認する最も信頼できる方法は、EOFを返すソケットからの読み取りを試みることです。
TCPは、接続のレイテンシと断続的な障害に耐性を持つように設計されています。これは、FIN, ACK
4ウェイ切断ハンドシェイクが発生しない場合に、切断を確実に検出するいくつかの課題にもつながります。
クライアントのkill -9
に表示されるのは、サーバーがTCP状態のCLOSE_WAIT
になり、TCPを待機している状態です。タイムアウト。これには時間がかかる場合があります。クライアントがなくなっても、カーネルがTCP切断ハンドシェイクを処理しなかった場合、サーバーはタイムアウトする必要があります。
私が覚えている場合、これにはさらに数秒かかる可能性があり、同じホスト上でクライアントとサーバーの両方を実行しているためにESTABLISHED
が引き続き表示される理由である可能性があります。