web-dev-qa-db-ja.com

接続が開いているか閉じているかを確認しますか?(LinuxのCの場合)

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データを書き込み、プログラムを閉じます。これを回避する方法は?

10
Sajad Bahmani

シグナルを処理しない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;
}
14
Sajad Bahmani

ソケットに書き込めるかどうかを確認する方法は、驚くべきことに、ソケットに書き込もうとすることです:-)

ソケットが閉じられている場合は、writeから-1リターンコードを取得し、errnoを調べて問題の内容を確認できます。

ソケットがまだ有効であるが、現時点でデータを書き込めない場合、writeは0を返します。read呼び出しも同様に動作し、-1ifを返します。問題がある。

基本的に、writeの場合:

  • -1が戻ってきた場合は、問題が発生しているため、errnoをチェックして、回復可能か致命的かを確認する必要があります。
  • 0が返されると、現時点では何も書き込むことができません(ネットワークのバックログまたはその他の問題である可能性がありますが、(まだ)致命的ではありません)。
  • 必要な値よりも小さい値を取得した場合は、someのデータが送信されています。次のサイクルで残りを送信できるように、ポインタを調整します。実行not正の戻り値は、ブロック全体が送信されたことを意味すると想定します。
  • 送信しようとしたバイト数と同じ数が返される場合は、バッファ全体の配信が受け入れられています。
  • 送信を要求した以上の結果が返ってきた場合は、カーネル開発者にいくつかの嫌なコメントを添えて電子メールを送信してください。 Linus他はそれを気に入るはずです:-)

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);

以前のシグナル処理を復元します。

17
paxdiablo

ソケットプログラミングは、かなり後になるまでエラーが発生したことを知らないことが多いため、かなり注意が必要です。

たとえば、書き込み先のマシンが異常にシャットダウンした場合、書き込み呼び出しは成功する可能性があります(内部OSバッファーに書き込むことができたため)が、閉じる呼び出し中にのみ失敗します。

ソケットがアクティブであることを確認するアプリケーション層の方法がない限り(つまり、メッセージを送信し、一定期間内に応答を要求する)、知る方法はありません。標準プロトコルを使用している場合は、エラーを処理するための何かがすでに存在している可能性があります。

したがって、簡単な答えは、ソケットに触れるほとんどすべての呼び出し(読み取り、書き込み、閉じるなど)からのエラーリターンをチェックする必要があるということです。

7
Chris Arguin