atom
2015年3月10日 14時18分
お世話になります。
佐藤です。
原因はプログラムによるものと思われますが対処方がわからないので対処法のご教授をよろしくお願いします。
現象
現在のプログラムは以下のような処理を想定しています。
(1) ソケット作成
sock = socket(AF_INET, SOCK_STREAM, 0);
(2) connect実施
connect(sock, (struct sockaddr *)&server, sizeof server);
(3) fdの追加
FD_SET(sock, &readfds);
(4) select()を使用して受信データを待つ(タイムアウトあり)
memcpy(&fds, &readfds, sizeof(fd_set);
select(max_fd+1, &fds, NULL, NULL, &tv);
(5) 受信データがある場合は受信データの処理し、処理終了後(6)へ
(6) 受信データとは関係なく行う処理(定期的に送信するメッセージなど)後(4) へ戻る
※(5)で回線切断と判断された場合はsocketを破棄して(1)から再度実行するようにしたい
現時点での問題点
(6) の"write"実行時にプログラムが終了してしまうことがある。
条件としては、相手側(サーバー)が切断されたあとに起こることがあるため、(4)、(5)による相手側の切断
の判定処理後に回線切断となり、(6)でwriteコマンドによる送信が生じているためと考えられます。
以下のいずれかの方法をとることを考えていますが対処可能でしょうか。また、どのように処理をすればい
いのでしょうか?
(1) write実行前にwrite可能かを識別する
(2) 相手側の回線切断後にwriteを実行してもプログラムが終了されないようにする
以上、対処方法などありましたらご教授ください。
コメント
atom
y.nakamura
中村です。
> 変更後:send(sock, data, lng, MSG_NOSIGNAL) ;
これでもいいですね。
> SIGPIPEのトラップについていまひとつわからなかったのですが
せっかくなので説明しておきます。
「トラップ」と書いたのがわかりにくかったかもしれません。
シグナルハンドラを設定するか無視するか、なのですけど、
無視するようにするだけでもいいと思います。
signal(SIGPIPE, SIG_IGN);
です。
SIGPIPEを無視するようにしてからwrite()するのと、
send(x,x,x,MSG_NOSIGNAL)するとので、
効果(動作)は同じだと思います。
どちらもソケットが切れたときにデータ送信しようとすると
-1でreturnしてerrno=EPIPEです。
--
なかむら
y.nakamura
2015年3月10日 14時53分
中村です。
> (6) の"write"実行時にプログラムが終了してしまうことがある。
> 条件としては、相手側(サーバー)が切断されたあとに起こることがあるため、(4)、(5)による相手側の切断
> の判定処理後に回線切断となり、(6)でwriteコマンドによる送信が生じているためと考えられます。
ソケットの切断で生じるのであれば、write時の
SIGPIPEによる強制終了だと思います。
> (1) write実行前にwrite可能かを識別する
これをやったとして(調べることができたとして)も、
write可能かを調べたあと、writeするまでの間に
ソケットが切れれば同じことです。
> (2) 相手側の回線切断後にwriteを実行してもプログラムが終了されないようにする
SIGPIPEをトラップしてみてください。
--
なかむら