2012-09-13 20 views
14

私はいくつかのデータをサーバにある時点で送信する必要のあるアプリケーションを持っています。簡単な方法は、接続を閉じて、何かを送信したいときにもう一度開くことです。しかし、私はデータを送信したいときに、私が最初にこの機能を使用して接続を確認するオープン接続を維持したい:ソケットが接続されているかどうかを確認してください

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

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

+3

http://stackoverflow.com/questions/4142012/how-to-find-the-socket-connection-state-in-c – BoBTFish

答えて

17

最初に確認してから送信しないでください。それは無駄な努力で、とにかく動作しません。あなたが確認したときと送信するときの間で状態が変わることがあります。あなたがやりたいことをして、失敗した場合はエラーを処理してください。

状態を確認するには、使用:

int error_code; 
int error_code_size = sizeof(error_code); 
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size); 
+1

真...ソケットがまだ接続されているかどうかをチェックするのが便利なことがあります。これを非ブロックに設定し、peek_msgで読み取ることは、ソケットがまだ接続されていることを確認するためのエラーコードを引き出す良い方法です。 –

+2

@RafaelBaptistaなぜですか? *を使用してチェックします。デビッドは上記の理由から、最初のテストは確実に機能しません。 – EJP

+0

@EJP:クライアント接続が生きていることを確認したいので、そうでない場合にリソースを無駄にしません。 – che

12

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

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

その後、あなた必見チェックerrnoにそれが失敗した場合。それはEAGAINで失敗する可能性があるか、それは明らかになどEBADFまたはENOTCONN


、ソケットが接続されているかどうかを「忘れる」を回避することですこれに対処する最も簡単かつクリーンな方法で失敗することができます。 recvが0を返すか、sendが返ると、ソケットが切断されると、EPIPEが返されます。

+2

これはしませんすべての接続障害を検出します。 send()だけがそれを行うことができます。 – EJP

+0

@EJPこれは事実です。私はちょうどオペレーションの解決策を改善していました。あなたが示唆しているのは、唯一の防弾ソリューションですが、送信する必要があります。 – cnicutar

2

デフォルトのTCPの使用では、(通常の終了以外の)デッドソケットの適時の検出が許可されないので、このような "is_connected"関数は実用的な目的ではほとんど役に立たないことをお勧めします。タイムリーな応答(またはその欠如)に基づいて生存している場合は、アプリケーション層のキープアライブおよびトラックを実装することを検討してください。

編集:投稿後BoBTFishのリンクが表示されますが、これは事実上同じことです。

関連する問題