8

boost::asio::io_serviceいくつかの非同期 TCP 通信を管理するために使用しています。つまり、 を作成し、boost::asio::ip::tcp::socketそれに を渡しio_serviceます。通信を開始すると、概略的には次のようになります。

Async Resolve -> Callback -> Async Connect -> Callback -> Async Write -> Callback -> Async Read

resolve や bind などの部分は省略しました。Socket がポートにバインドされており、ホスト名が解決されていると仮定してください (したがって、接続はエンドポイントへの実際の接続を確立することを意味します)。

ポイントは、同じio_serviceオブジェクトで複数の非同期接続を開始できることです。これは、たとえば、私のio_serviceスレッドでプログラムがAsync Write何らかのデータを処理しようとしている間に、メインスレッドがAsync Resolveon Socket で呼び出すことを意味します (ただし、同じio_serviceです)。これは、io_service現在、並行して行う作業があることを意味します。知りたいのは、作業の優先順位をどのようにするかです。

例えばこんな感じです

Main Thread              |      io_service Thread
-------------------------+-----------------------------------------------
SocketA->Async Connect   |
//Some other Stuff       |     SocketA->Callback from Async Connect
                         |     SocketA->Async Write
SocketB->Async Connect   |      
                         |     --> ?

この時点で、私はそれがどのように機能するのかよくわからないことを認めなければなりませんio_service. 4 行目には、実行する必要がある 2 つの異なる非同期関数があります。

と を同時にio_service行うことができますか? その場合、最初に終了した関数からのコールバックが常に呼び出されることは明らかです。Async ConnectAsync Write

がそうすることio_serviceできない場合、どの順序で作業を行いますか? が最初に呼び出される場合SocketA Async Write、そのコールバックも最初に呼び出されます。実際には、SocketA での操作全体が完了するまで、常に作業が行われます。

編集 :

ereOns のコメントによると、質問をもう少し正確にしようとしています。

io_serviceスレッドの観点から-SocketA Async Connect呼び出しは非同期ですか、それとも同期ですか? 私のメインスレッドの観点からは、もちろん非同期です(コマンドをディスパッチしてから続行します)。しかし、io_serviceスレッドでは、この特定Connectの呼び出しは他の操作をブロックしますか?

言い換えればio_service、1 つのソケットが別のソケットを読み込んでいる間に、1 つのソケットに接続できますか?

Async Connectもう 1 つの例は、メイン関数で2 を次々に呼び出した場合です。

SocketA->AsyncConnect();
SocketB->AsyncConnect();

SocketA からのホストが少し遅く、応答に 2 秒かかるとします。したがって、SocketA が接続しようとしている間に SocketB も接続しますか、それとも SocketA が終了/タイムアウトするまで待機する必要がありますか?

4

2 に答える 2

4

すべての作業は、実行されるスレッドで行われio_service.run()ます。

ただし、async_メソッドの呼び出しはこの特定のスレッドをブロックしませんio_service.run()。複数のイベントで呼び出さselect()れた場合とまったく同じように動作し、そのようなイベントが発生するたびに「戻ります」(コールバックを呼び出します)。つまり、次のように呼び出した場合:

socketA->async_connect();
socketB->async_connect();

socketB前に接続することもできsocketA、関連するコールバックが最初に呼び出されますが、スレッドのio_service.run()実行中のままです。

これが Boost Asio のすべての利点です。より適切な場合にイベントをポーリング、待機、および発生させることに細心の注意を払い、「簡単」な部分を残します。

于 2012-05-10T12:09:58.367 に答える
1

ここで、非同期操作の実行順序を予測しようとしないでください。async_connect信号を送るだけでio_service、すぐに戻ります。実際の作業はio_serviceオブジェクトのイベント処理ループ ( io_service::run) で行われますが、正確な詳細はわかりません。OS 固有の非同期 IO 関数を使用する可能性が最も高いです。

あなたが達成しようとしていることは明らかではありません。おそらく、同期操作を使用する必要があります。おそらく、スレッド同期機能を使用する必要があります。多分io_service::run_oneあなたを助けるでしょう(それはせいぜい1つのハンドラーを実行します)。

io_service::runスレッドプールを作成して、別々のスレッドで複数回呼び出したいと思うかもしれません。そうすれば、1 つの長い完了ハンドラーが他のすべてをブロックすることはありません。

boost::asio::io_service service;
const size_t ASIO_THREAD_COUNT = 3;
boost::thread_group threadGroup;
for (size_t i = 0; i < ASIO_THREAD_COUNT; ++i)
        threadGroup.create_thread(boost::bind(&boost::asio::io_service::run,
            &service, boost::system::error_code()));
于 2012-05-10T13:05:02.270 に答える