2

私は現在、ソケットselect()呼び出しに関連して作成したプロキシサーバーのバグを修正しようとしています。私は(SocketReactorを使用して)Poco C ++ライブラリを使用しており、問題は実際にはバグである可能性のあるPocoコードにありますが、まだ確認を受け取っていません。

何が起こっているのかというと、接続が突然終了したときはいつでも、ソケットselect()呼び出しがすぐに戻ってきます。これは、私が意図していることだと思いますか?とにかく、読み取り可能なファイル記述子のセット内の切断されたすべてのソケットを返しますが、問題は、Pocoがコードを配置する場所であるonReadableイベントハンドラーを起動しようとすると、「ソケットが接続されていません」という例外がスローされることです。これに対処します。例外がサイレントにキャッチされ、onReadableイベントが発生しない場合、select()呼び出しはすぐに戻り続け、SocketReactorで無限ループが発生します。

Pocoコードを変更して、例外をサイレントにキャッチするのではなく、onDisconnectedなどと呼ばれる新しいイベントを発生させて、クリーンアップを実行できるようにすることを検討していました。

私の質問は、select()呼び出しを使用してソケットが異常に閉じたかどうかを判断するための洗練された方法はありますか?例外メッセージを使用してこれがいつ発生したかを判断することを考えていましたが、これは私には汚いようです。

4

3 に答える 3

2

私はこれと同じ問題を抱えていました。これを回避する唯一の方法は、クライアントアプリケーションの終了コードを制御することです。私が使用した解決策は、クライアント側でリアクターが終了する前にシャットダウン信号を送信することでした。次に、サーバーでソケットを閉じるだけです。

//Client:
//Handler Class: onWrite
Packet p = Packet::Shutdown();

if (p.fn == "shutdown")
{
    _reactor.stop();
    delete this;
}

//Server
//Accepter Class: onRead
if (p.fn == "shutdown")
{
    printf("%s has disconnected", _username.c_str());
    _socket.close();
    delete this;
}
于 2012-01-01T11:51:12.793 に答える
1

をキャッチするだけConnectionResetExceptionOnReadable()(処理しますReadableNotification)、「ピアによる接続リセット」を適切に処理します。

catch(Poco::Net::ConnectionResetException &ex)
{
    _socket.shutdownSend();
    delete this;
}
于 2012-09-16T15:00:29.907 に答える
1

あなたは正しいレミーのようです。次のコードを使用して、ソケットが切断されたかどうかを区別することができました(これはPoco / Net / src / SocketImpl.cppに追加されました)。

bool SocketImpl::isConnected()
{
int bytestoread;
int rc;
fd_set fdRead;

FD_ZERO(&fdRead);
FD_SET(_sockfd, &fdRead);

struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 250000;

rc = ::select(int(_sockfd) + 1, &fdRead, (fd_set*) 0, (fd_set*) 0, &tv);
ioctl(FIONREAD, &bytestoread);

return !((bytestoread == 0) && (rc == 1));
}

私の理解では、これはselect()の呼び出しを使用してソケットが読み取り可能かどうかをチェックし、次にそのソケットで使用可能な実際のバイト数をチェックします。ソケットが読み取り可能であると報告したが、バイトが0の場合、ソケットは実際には接続されていません。

これはここでの私の質問に答えますが、Poco SocketReactorコードでこれを修正する方法がわからないため、残念ながらPocoの問題は解決していません。私はDisconnectNotificationという新しいイベントを作成しようとしましたが、閉じたソケットでのReadNotificationの場合と同じエラーがスローされるため、残念ながらそれを呼び出すことができません。

于 2010-05-03T07:17:24.930 に答える