5

私のコードでは、boost::asio と io_service を 1 つのスレッドで使用して、さまざまなソケット操作を実行しています。boost::system::error_codeすべての操作は非同期であり、すべてのハンドラーは(特に) に依存してboost::asio::error::operation_aborted操作の結果を決定します。

ロジックを変更して複数の同時接続を作成し、最速の接続を選択するまでは、完全にうまく機能しています。つまり、最初のasync_read_someハンドラーが起動すると、他のソケット (シャットダウン、クローズなどすべて) をキャンセルし、現在のソケットに進みます。95% のケースで、他のソケットの読み取りハンドラーが operation_aborted エラーで呼び出されます。ただし、これらの読み取りハンドラーがエラーなしで呼び出され、N バイトを正常に受信したことが示されることがあります。

しかし、socket::cancel() のドキュメントには次のように記載されています。

この関数により、すべての未解決の非同期接続、送信、および受信操作がただちに終了し、キャンセルされた操作のハンドラーにboost::asio::error::operation_abortedエラーが渡されます。

operation_abortedでは、質問:本番コードのエラーを本当に信頼できるでしょうか? 可能であれば、Boost 1.46.1 からの Asio のバグですか? できない場合、これに関する公式文書はありますか?

4

2 に答える 2

13

わかりました、答え:

  1. operation_abortedいいえ、エラーだけに頼ることはできません。
  2. もちろん、これはAsioのバグではなく、私の側の経験不足です。
  3. 公式ドキュメントが少しあります。ソケットではなくタイマー用ですが、同じ原則が適用されます。

cancel()が呼び出されたときにタイマーがすでに期限切れになっている場合、非同期待機操作のハンドラーは次のようになります。

  • すでに呼び出されています。また
  • 近い将来、呼び出しのためにキューに入れられました。

基本的に、io_serviceに単一のスレッドを使用すると、一部のハンドラーの実行中にすべての操作がブロックされるという仮定は間違っていました。

私が報告している動作は実際には非常に理にかなっており、Asioを使用するすべての人がそれを知っているようです。私はAsioのメーリングリストをくまなく調べて、このテーマに関する多くの議論をここここここ、そしてここで見つけました。

たとえば、ハンドラー内にいる間は、ソケットキャンセルの呼び出しに取り掛かる前に、書き込み操作が正常に完了し、その完了ハンドラーがキューにポストされる場合があります。私が理解しているように、エラーコードは、ハンドラーがキューからピックされて実行されたときのソケットの状態ではなく、完了した操作のステータスによって決定されます。

于 2012-05-30T19:21:14.420 に答える
2

同時に確立する2つの接続について考えてみます。両方のハンドラーが起動し、1つが最初に処理され、2つ目がキュー内にあります(または別のスレッドで処理されます)。そのような例をもっと考えることができます。

したがって、要件を実装するには、もう少しロジックが必要です。

于 2012-05-23T11:26:25.920 に答える