以下では、TCP の通信当事者のうち、説明の便宜上、通信当事者を A と B に置き換えます。
TCP プロトコルによれば、A が接続を閉じた後も B がデータを送信し続けると、B は A の RST 応答を受信します。 B がデータの送信を続ける場合、システムは SIGPIPE 信号を送信して、接続が切断されたことを通知し、送信を停止します。
SIGPIPE シグナルに対するシステムのデフォルトの処理動作では、プロセス B を終了させます。
SIGPIPE 信号に対するオペレーティング システムのデフォルトの処理動作は非常に不親切です。これを分析してみましょう。
TCP 通信は全二重チャネルであり、2 つの単信チャネルに相当し、接続の各端が 1 つのチャネルを担当します。
ピアが「閉じる」場合、意図は 2 つのチャネル全体を閉じることですが、ローカル エンドは FIN パケットのみを受信します。
TCP プロトコルの規定によれば、一方の端が担当する一方向チャネルを閉じると、引き続きデータを受信できますが、データを送信できなくなります。
言い換えると、TCP プロトコルの制限により、通信側はピアのソケットが close または shutdown を呼び出したかどうかを知ることができません。
リーリーシャットダウン関数のパラメータ「how」は、SHUT_RD、SHUT_WR、または SHUT_RDWR を閉じるように設定できます。これは、受信チャネルと送信チャネルを個別に閉じるか、送信チャネルと受信チャネルを同時に閉じるかを示すために使用されます。
FIN パケットを受信したソケットで read/recv メソッドを呼び出します。受信バッファが空の場合は 0 が返され、これは接続が閉じられたことを示すとよく言われます。ただし、最初に write/send メソッドを呼び出したとき、送信バッファに問題がなければ正しい書き込みが返されます(つまり、write/send 関数の戻り値が 0 より大きい)が、送信されたメッセージにより、ピアは RST メッセージで応答します。前回プログラムが write/send 関数を呼び出したときは正常だったため、再度 write/send 関数を呼び出そうとしたときに SIGPIPE シグナルが生成され、プロセスが終了してしまいました。
このデフォルトの動作は、同時に多くのクライアントにサービスを提供する必要がある、特にバックエンド サービス向けのプログラムを開発するためのものです。プロセス全体が終了できず、他のクライアントにサービスを提供し続けることはできません。特定のクライアントへの接続。
この現象を回避するには、SIGPIPE 信号をキャプチャして処理するか、信号を無視することができます。信号を無視するためのコードは次のとおりです:
リーリーこの設定の後、write/send メソッドが 2 回目に呼び出されるとき、-1 が返され、errno エラー コードが SIGPIPE に設定されるため、プログラムはピアが閉じられたことを認識します。
以上がLinux SIGPIPE 信号の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。