web-dev-qa-db-ja.com

Linuxはアプリケーションの終了時にソケットを閉じることをいつ/どのように決定しますか?

サーバープロセスとクライアントプロセスが同じLinuxマシンで実行されています。

場合によっては、クライアントをkill -9すると、tcpdumpFIN, ACKメッセージが送信されることがわかります。もちろん、死んだクライアントはSIGKILLで残忍に死んでいるので、それはできませんでした。したがって、Linux OSが接続のクローズを処理すると思います。

時々、connection-close-handlingが表示されず、接続が「確立」されたままになります(netstatによる)。

Linux ubuntu 4.4.0-53-genericで接続が閉じられるのをいつも見ています。
ときどきLinux 3.13.11(Ubuntuではなく純粋なカーネル)で接続が閉じられているのがわかります。

私の質問は:

  1. Linuxは接続のクローズを処理しますか?
    1.1 SIGKILL
    1.2。アプリケーションが適切に閉じたが、close()を呼び出さない場合
  2. この機能は、カーネルのバージョン3.13.114.4.0の間で変更されましたか? Ubuntuには何かありますか?
  3. これらの2つのプロセスが同じLinuxマシン上にない場合はどうなりますか?それは同じように動作しますか?
  4. 接続が「確立」されたままになることがあるのはなぜですか?
  5. TCP keepaliveソケットオプションを知っています。Linuxが実際に接続のクローズを処理する場合。なぜそれらが存在するのですか?FIN, ACKパケットがドロップする場合のみ?
5
hudac

幅広い質問。おそらく、特定のカーネルバージョン間のカーネルTCPスタックについての質問を誰かが検討する可能性があります。

いくつかの一般的な答え:

クライアント側から

  1. SIGKILLシグナルが発生すると、カーネルはプログラムの実行を終了し、とりわけ、プロセスの開いているファイル記述子を閉じます。 TCPソケットは、フラッシュされ、TCPシャットダウンプロセスを実行する必要があるという点で、カーネルによって通常のファイルとは少し異なって処理されます。

    クライアントからの即時の「FIN、ACK」と長いソケットのシャットダウンの違いは、クライアントアプリケーションが終了したときにクライアントTCP接続がどのような状態であったかによって異なります。しかし、一般的にカーネルはアプリケーションの開いているソケットを閉じます。

サーバー側から

  1. サーバーは、クライアントがいつ切断するかを常に認識しているわけではありません。クライアントがハングアップしたかどうかを確認する最も信頼できる方法は、EOFを返すソケットからの読み取りを試みることです。

    TCPは、接続のレイテンシと断続的な障害に耐性を持つように設計されています。これは、FIN, ACK 4ウェイ切断ハンドシェイクが発生しない場合に、切断を確実に検出するいくつかの課題にもつながります。

概要

クライアントのkill -9に表示されるのは、サーバーがTCP状態のCLOSE_WAITになり、TCPを待機している状態です。タイムアウト。これには時間がかかる場合があります。クライアントがなくなっても、カーネルがTCP切断ハンドシェイクを処理しなかった場合、サーバーはタイムアウトする必要があります。

私が覚えている場合、これにはさらに数秒かかる可能性があり、同じホスト上でクライアントとサーバーの両方を実行しているためにESTABLISHEDが引き続き表示される理由である可能性があります。

3
111---