web-dev-qa-db-ja.com

Cでソケット接続状態を見つける方法は?

TCP接続。サーバーはクライアントからデータを読み取るだけです。接続が失われると、クライアントはパイプ(壊れたパイプ)へのデータの書き込み中にエラーを受け取りますが、サーバーはまだそのパイプをリッスンしています。接続がアップかどうかを確認する方法はありますか?

25
Blacklabel

次のようにgetsockoptを呼び出すことができます。

int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (socket_fd, SOL_SOCKET, SO_ERROR, &error, &len);

ソケットが起動しているかどうかをテストするには:

if (retval != 0) {
    /* there was a problem getting the error code */
    fprintf(stderr, "error getting socket error code: %s\n", strerror(retval));
    return;
}

if (error != 0) {
    /* socket has a non zero error status */
    fprintf(stderr, "socket error: %s\n", strerror(error));
}
33
Simone

ソケットがまだ接続されているかどうかを確実に検出する唯一の方法は、定期的にデータを送信することです。通常、クライアントが無視するアプリケーションレベルの「ping」パケットを定義する方が便利ですが、そのような機能がなくてもプロトコルがすでに指定されている場合は、 SO_KEEPALIVE ソケットオプション。 winsockのドキュメントにリンクしましたが、すべてのBSDのようなソケットスタックで同じ機能が利用できるはずです。

11
Chris Becke

TCPキープアライブソケットオプション(SO_KEEPALIVE)は、このシナリオで役立ち、接続が失われた場合にサーバーソケットを閉じます。

4
blaze

同様の問題がありました。サーバーがクライアントに接続されているのか、クライアントがサーバーに接続されているのかを知りたい。このような状況では、recv関数の戻り値が役立ちます。ソケットが接続されていない場合、0バイトを返します。したがって、これを使用してループを壊し、関数の余分なスレッドを使用する必要はありませんでした。専門家がこれが正しい方法であると感じた場合も、これを使用することがあります。

2
Parth Shah

使用してみてください:getpeername関数。

接続がダウンすると、errnoになります:ENOTCONN-ソケットは接続されていません。あなたにとってダウンを意味します。

それ以外の場合(他に障害がない場合)、戻りコードは0-> UPを意味します。

resources:manページ: http://man7.org/linux/man-pages/man2/getpeername.2.html =

1
Tal Bar

get sock optは多少役立つかもしれませんが、SIGPIPE用にシグナルハンドラをインストールする別の方法があります。基本的に、ソケット接続が切断されるたびに、カーネルはプロセスにSIGPIPEシグナルを送信し、必要なことを実行できます。しかし、これでも接続の状態を知るためのソリューションを提供しません。お役に立てれば。

1
chandank

poll呼び出しを介してソケット接続状態を確認する簡単な方法があります。最初に、POLLINイベントがあるかどうかにかかわらず、ソケットをポーリングする必要があります。

  1. ソケットが閉じられておらず、読み取るデータがある場合、readはゼロ以上を返します。
  2. ソケットに新しいデータがない場合、POLLINreventsは0に設定されます。
  3. ソケットが閉じている場合、POLLINフラグは1に設定され、読み取りは0を返します。

以下に小さなコードスニペットを示します。

int client_socket_1, client_socket_2;
if ((client_socket_1 = accept(listen_socket, NULL, NULL)) < 0)
{
    perror("Unable to accept s1");
    abort();
}
if ((client_socket_2 = accept(listen_socket, NULL, NULL)) < 0)
{
    perror("Unable to accept s2");
    abort();
}
pollfd pfd[]={{client_socket_1,POLLIN,0},{client_socket_2,POLLIN,0}};
char sock_buf[1024]; 
while (true)
{
    poll(pfd,2,5);
    if (pfd[0].revents & POLLIN)
    {
        int sock_readden = read(client_socket_1, sock_buf, sizeof(sock_buf));
        if (sock_readden == 0)
            break;
        if (sock_readden > 0)
            write(client_socket_2, sock_buf, sock_readden);
    }
    if (pfd[1].revents & POLLIN)
    {
        int sock_readden = read(client_socket_2, sock_buf, sizeof(sock_buf));
        if (sock_readden == 0)
            break;
        if (sock_readden > 0)
            write(client_socket_1, sock_buf, sock_readden);
    }
}
1
yanpas