26

ある時点でデータをサーバーに送信する必要があるアプリケーションがあります。簡単な方法は、接続を閉じてから、何かを送信したいときにもう一度開くことです。しかし、接続を開いたままにしたいので、データを送信したいときは、まずこの関数を使用して接続を確認します。

bool is_connected(int sock)
{
    unsigned char buf;
    int err = recv(sock,&buf,1,MSG_PEEK);
    return err == -1 ? false : true;
}

悪い点は、これが機能しないことです。受信するデータがない場合はハングします。私に何ができる?接続がまだ開いているかどうかを確認するにはどうすればよいですか?

4

3 に答える 3

31

確認してから送信しないでください。無駄な労力であり、とにかく機能しません。ステータスは、確認時と送信時とで変わる可能性があります。やりたいことをして、失敗した場合はエラーを処理してください。

ステータスを確認するには、次を使用します。

int error_code;
int error_code_size = sizeof(error_code);
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size);
于 2012-09-13T17:38:04.327 に答える
13

O_NONBLOCKを使用して設定することにより、非ブロッキング動作を有効にする必要がありますfcntl。ノンブロッキング読み取りを行うための簡単だが非標準的な方法の 1 つは、次を使用することです。

recv(sock, &buf, 1, MSG_PEEK | MSG_DONTWAIT);

その後、失敗した場合は errno を確認する必要があります。またはなどで失敗EAGAINする可能性があります。EBADFENOTCONN


明らかに、これに対処する最も簡単でクリーンな方法は、ソケットが接続されているかどうかを「忘れる」ことを避けることです。recvaが 0 または aをsend返すと、ソケットが切断されるかどうかがわかりますEPIPE

于 2012-09-13T08:47:27.920 に答える
4

デフォルトで TCP を使用すると、デッド ソケット (通常のクロージャー以外) をタイムリーに検出することができないため、このような「is_connected」関数はすべての実用的な目的でほとんど役に立たないことをお勧めします。アプリケーション層のキープアライブの実装を検討し、タイムリーな応答 (またはその欠如) に基づいて、それが生きているかどうかを追跡します。

編集: 投稿後、BoBTFish のリンクが表示されますが、これは実質的に同じものです。

于 2012-09-13T17:34:41.520 に答える