Linuxのソケットプログラミングでは、ソケットにデータを書き込む必要がありますが、ソケットが開いているか閉じているかわかりません。ソケットが読み取らずに開閉していることを知る方法は?
printf("befor read%d\n", n);
bzero(buffer, MAX_SIZE_BUFFER);
n = read(sockfd, buffer, MAX_SIZE_BUFFER - 1);
printf("after read%d\n", n);
if (n <= 0)
{
break;
}
printf("befor write%d, s: %d \n", n , sockfd);
n = write(newsockfd, buffer, n);
if (n <= 0)
{
break;
}
Sockfdから読みましたが、この接続が開いていることを確認しました。 newsockfdにバッファを書き込むタイミングnewsockfdが開いているか閉じているかわからないnewsockfdが閉じていることを確認する方法は?
私は問題を知っています。書き込み中に接続が閉じられました。たとえば、500接続で1024データを書き込み、プログラムを閉じます。これを回避する方法は?
シグナルを処理しない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;
}
ソケットに書き込めるかどうかを確認する方法は、驚くべきことに、ソケットに書き込もうとすることです:-)
ソケットが閉じられている場合は、write
から-1
リターンコードを取得し、errno
を調べて問題の内容を確認できます。
ソケットがまだ有効であるが、現時点でデータを書き込めない場合、write
は0を返します。read
呼び出しも同様に動作し、-1
ifを返します。問題がある。
基本的に、write
の場合:
-1
が戻ってきた場合は、問題が発生しているため、errno
をチェックして、回復可能か致命的かを確認する必要があります。0
が返されると、現時点では何も書き込むことができません(ネットワークのバックログまたはその他の問題である可能性がありますが、(まだ)致命的ではありません)。pdate: 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);
以前のシグナル処理を復元します。
ソケットプログラミングは、かなり後になるまでエラーが発生したことを知らないことが多いため、かなり注意が必要です。
たとえば、書き込み先のマシンが異常にシャットダウンした場合、書き込み呼び出しは成功する可能性があります(内部OSバッファーに書き込むことができたため)が、閉じる呼び出し中にのみ失敗します。
ソケットがアクティブであることを確認するアプリケーション層の方法がない限り(つまり、メッセージを送信し、一定期間内に応答を要求する)、知る方法はありません。標準プロトコルを使用している場合は、エラーを処理するための何かがすでに存在している可能性があります。
したがって、簡単な答えは、ソケットに触れるほとんどすべての呼び出し(読み取り、書き込み、閉じるなど)からのエラーリターンをチェックする必要があるということです。