TCP接続。サーバーはクライアントからデータを読み取るだけです。接続が失われると、クライアントはパイプ(壊れたパイプ)へのデータの書き込み中にエラーを受け取りますが、サーバーはまだそのパイプをリッスンしています。接続がアップかどうかを確認する方法はありますか?
次のように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));
}
ソケットがまだ接続されているかどうかを確実に検出する唯一の方法は、定期的にデータを送信することです。通常、クライアントが無視するアプリケーションレベルの「ping」パケットを定義する方が便利ですが、そのような機能がなくてもプロトコルがすでに指定されている場合は、 SO_KEEPALIVE ソケットオプション。 winsockのドキュメントにリンクしましたが、すべてのBSDのようなソケットスタックで同じ機能が利用できるはずです。
TCPキープアライブソケットオプション(SO_KEEPALIVE)は、このシナリオで役立ち、接続が失われた場合にサーバーソケットを閉じます。
同様の問題がありました。サーバーがクライアントに接続されているのか、クライアントがサーバーに接続されているのかを知りたい。このような状況では、recv関数の戻り値が役立ちます。ソケットが接続されていない場合、0バイトを返します。したがって、これを使用してループを壊し、関数の余分なスレッドを使用する必要はありませんでした。専門家がこれが正しい方法であると感じた場合も、これを使用することがあります。
使用してみてください:getpeername関数。
接続がダウンすると、errnoになります:ENOTCONN-ソケットは接続されていません。あなたにとってダウンを意味します。
それ以外の場合(他に障害がない場合)、戻りコードは0-> UPを意味します。
resources:manページ: http://man7.org/linux/man-pages/man2/getpeername.2.html =
get sock optは多少役立つかもしれませんが、SIGPIPE用にシグナルハンドラをインストールする別の方法があります。基本的に、ソケット接続が切断されるたびに、カーネルはプロセスにSIGPIPEシグナルを送信し、必要なことを実行できます。しかし、これでも接続の状態を知るためのソリューションを提供しません。お役に立てれば。
poll
呼び出しを介してソケット接続状態を確認する簡単な方法があります。最初に、POLLIN
イベントがあるかどうかにかかわらず、ソケットをポーリングする必要があります。
read
はゼロ以上を返します。POLLIN
のrevents
は0に設定されます。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);
}
}