funini.com 自由研究 C/C++ ソケット

ソケット

サーバ・クライアントプログラムを C で書いて、通信の実験中、 クライアントを Ctrl-c (C-c) で止めると、なぜかサーバも道連れになってしまう。
落ちるところは普通の send()。返り値がいくつ、とかチェックする間もなく落ちてしまう。 でも、クライアントを C-z で一度止めて kill したときには落ちない。 パケットキャプチャしてみると、どちらのケースでも FIN ではなく RST (リセット)パケットが飛んでいる。
いろいろ調べてみると、間が悪くRST パケットが飛んでくると、 SIGPIPE が返される模様。それで、SIGPIPE のシグナルハンドラが動いて、サーバプロセスも 道連れになってしまうみたい。
この挙動を止めるには、以下のように書いて SIGPIPE のシグナルハンドラを無効にする。
#include 

...

int main(){

signal( SIGPIPE , SIG_IGN );

でも、man を見ていたら、send のオプションで抑制することもできるらしい。

MSG_NOSIGNAL (Linux 2.2 以降) 
ストリーム指向のソケットで相手側が接続を切断した時に、エラーとして 
SIGPIPE を送信しないように要求する。この場合でも EPIPE は返される。

ちなみに、sigpipe は、元々パイプでつながったプロセスのために作られたもの。 例えば、

$ grep なんとか | head -10

としたときに、右側の head は 10行読んだら、左の grep の処理はもう不要になってしまう。
こういうとき、左のプロセスに対し、SIGPIPEが送られる。