2012-05-23 4 views
5

私のコードは、シングルスレッドでboost :: asioとio_serviceを使用してさまざまなソケット操作を実行します。すべての操作は非同期であり、すべてのハンドラは操作の結果を判断するためにboost::system::error_code(特にboost::asio::error::operation_aborted)に依存します。boost :: asioキャンセル後にエラーなしで呼び出されるasyncハンドラ

の接続を同時に行い、最速のものを選択するようにロジックを変更するまでは、正常に動作しています。つまり、最初のasync_read_someハンドラが起動すると、他のソケット(シャットダウン、クローズ - すべて)をキャンセルし、現在のソケットを処理します。 95%のケースでは、他のソケットの読み取りハンドラがoperation_abortedエラーで呼び出されます。しかし時々、これらの読み取りハンドラはエラーなしで起動され、Nバイトを正常に受信したことを伝えます。

しかし、ソケットのドキュメントは::キャンセル()states

この機能は、すべての未処理の非同期の送信、接続原因と はすぐに終了する操作を受信し、 キャンセル操作のためのハンドラが渡されますboost::asio::error::operation_abortedエラーです。

質問:プロダクトコードのエラーoperation_abortedに本当に依存できますか?もしできれば、ブースト1.46.1からのAsioのバグですか?私ができない場合、これに関する正式な文書はありますか?

+1

あなたのケースでは、キャンセルが呼び出される前に複数のハンドラが「成功」しているようです。 'operation_aborted'を利用して、まだ実行されていないハンドラに渡すことができます(呼び出されるのを待っています)。 – Chad

答えて

11

[OK]を、解答:

  1. いいえ、私は唯一のoperation_abortedエラーに頼ることはできません。
  2. もちろん、Asioのバグではなく、自分の経験が不足しているだけです。
  3. 少しの公式documentationがあります。それはタイマーではなく、ソケットのためだ、しかし、同じ原理が適用されます:

タイマーがすでにキャンセルしたときに有効期限が切れている場合は()と呼ばれ、その後、非同期待機操作のためのハンドラは以下となります。

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

基本的に、私は私がio_serviceのための単一のスレッドを使用する場合、いくつかのハンドラが実行している間、その後、すべての操作がブロックされることを前提に間違っていました。

私が実際に報告している行動はかなり意味があり、Asioを使用するすべての人がそれを知っているようです。私はAsioのメーリングリストに詰め込み、hereherehere、およびhereについて多くの議論を見つけました。例えば

あなたはハンドラ内でいますが、その完了ハンドラはキューにポストさせる、キャンセル ソケットを呼び出すに周りの持って前にある ながら、書き込み操作が正常に完了する可能性があります。 エラーコードは、 ハンドラがキューから取り出され実行された時点のソケットの状態ではなく、完了した 操作のステータスによって決まります。

+1

+1自分の質問に対するすっきりした答え –

2

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

あなたの要件を実装するには、もう少し論理が必要です。

関連する問題