7

Boostのasioライブラリを使用してサーバーを作成しています。サーバーは、Connectionオブジェクトのコレクション(boost :: asio :: tcp :: socketのラッパークラス)を使用して、多くの同時接続を処理します。Connectionクラス内では、socket.async_read_some(...)を使用してソケットが常に読み取られ、新しいデータで読み取りハンドラーが呼び出されるたびに、socket.async_read_some()がすぐに再度呼び出され、さらにデータが読み取られます。

これで、サーバーが何らかの理由でクライアントを切断することを決定する可能性があるため、当然のこととして、connection.close()を呼び出し、次にsocket.close()を呼び出します。これにより、保留中のすべての非同期操作がキャンセルされます。これにより、読み取りハンドラー(クラスConnection内のメソッドにバインドされている)がboost :: asio :: error::operation_abortedで呼び出されます。そして私の問題は、これが起こらないようにすることです。

socket.close()の後、ソケットと接続を破棄してから、サーバーのアクティブなクライアントのリストからそのポインターを削除したいと思います。ただし、読み取りハンドラーはio_service.run()の次の反復まで呼び出されません。つまり、ハンドラーがで呼び出されるまで、ソケットまたはsocket.async_read_some()に渡した読み取りハンドラーをすぐに破棄することはできません。エラー。だから私はそれらのオブジェクトの破壊をどうにかして遅らせなければなりません。うざい。

どちらかに安全な方法はありますか

  • ハンドラーを呼び出さずに保留中の非同期操作をキャンセルして、socket.close()の直後にソケットを安全に破棄できるようにします。
  • これ以上ハンドラーを呼び出すことができない場合を安全に知るため

それとも私はこれに完全に間違った方法でアプローチしていますか?

4

1 に答える 1

4

async.operationが完了すると(成功またはエラーのいずれかで)、その完了ハンドラーが呼び出されます。これは重要な保証であり、この動作を「ハッキング」するのは良い考えではないと思います。ユースケースで発生した問題は、通常、shared_ptr(shared_from_thisイディオム)を使用して解決されshared_ptr<Connection>ます。ハンドラーにバインドし、operation_aborted(またはその他のエラー)が発生したときに別のasync_readを発行しないでください。これにより、すべてのハンドラーが完了します。 Connectionオブジェクトはそのソケットで破棄されます。

于 2012-05-17T14:13:50.420 に答える