シグナルを処理しない write() の代わりに send() を使用します:
bzero(buffer, MAX_SIZE_BUFFER);
n = read(sockfd, buffer, MAX_SIZE_BUFFER - 1);
printf("after read%d\n", n);
if (n <= 0)
{
break;
}
n2 = send(newsockfd, buffer, n, MSG_NOSIGNAL);
if (n2 == -1)
{
close(sockfd);
close(newsockfd);
return;
}
if (n2 != n)
{
break;
}
エラーが発生したのはかなり後になるまでわからないことが多いため、ソケット プログラミングはややこしい場合があります。
たとえば、書き込んでいるマシンが異常終了した場合、(内部 OS バッファに書き込むことができたので) write 呼び出しは成功するかもしれませんが、close 呼び出し中に失敗するだけです。
ソケットがアクティブであることを確認するアプリケーション層の方法 (つまり、メッセージを送信し、一定期間内に応答を要求する) がない限り、知る方法はありません。標準プロトコルを使用している場合、エラーを処理するための何かがすでに存在している可能性があります。
したがって、短い答えは、ソケットに触れるほぼすべての呼び出し (読み取り、書き込み、閉じるなど) からのエラー リターンをチェックする必要があるということです。
ソケットに書き込めるかどうかを確認する方法は、驚くべきことに、ソケットに書き込んでみることです:-)
ソケットが閉じられている場合は、-1
が返されます write
からの戻りコード errno
を調べることができます 問題が何であったかを確認してください。
ソケットがまだ有効であるが、現時点でデータを書き込むことができない場合、 write
0 を返します。read
call も同様に動作し、-1
を返します。 問題があれば。
基本的に write
用 :
-1
が返ってきたら 、問題が発生しました。errno
を確認してください 回復可能か致命的かを確認します。0
が返ってきたら 、その場合、現時点では何も書くことができません (ネットワークのバックログまたはその他の問題である可能性がありますが、(まだ) 致命的ではないことは間違いありません)。- 必要な値よりも低い値が得られた場合は、some のデータが送信されました。次のサイクルで残りを送信できるように、ポインターを調整します。 しない 正の戻り値は、ブロック全体が送信されたことを意味すると想定します。
- 送信しようとしたバイト数と同じ数が返された場合、バッファ全体が配信のために受け入れられています.
- 送信を要求した以上の返信があった場合は、辛辣なコメントを添えてカーネル開発者にメールを送ってください。 Linus 達はそれを気に入るはずです :-)
更新: caf がコメントで指摘したように、シグナル処理を考慮するのを忘れていました。壊れたパイプ信号または write
を無視する必要があります そのシグナルを上げることで内部的に失敗します。
以下を挿入することでこれを行うことができます:
struct sigaction new_actn, old_actn;
new_actn.sa_handler = SIG_IGN;
sigemptyset (&new_actn.sa_mask);
new_actn.sa_flags = 0;
sigaction (SIGPIPE, &new_actn, &old_actn);
ソケット機能を使い始める前に。次に使用できます:
sigaction (SIGPIPE, &old_actn, NULL);
以前のシグナル処理を復元します。