ZeroMQへのソケットを取得することは、戦いの最小の部分です。ZeroMQは、TCP上に階層化されたプロトコルに基づいているため、このルートを使用する場合は、カスタムBoost.Asioio_service内でZeroMQを再実装する必要があります。Boost.Asioを使用して非同期ENetサービスを作成するときに、最初にBoost.Asio UDPサービスを使用してENetクライアントからのトラフィックをキャッチしようとしたときに、同じ問題が発生しました。ENetはUDP上に階層化されたTCPのようなプロトコルであるため、その時点で達成したのは、事実上役に立たない状態のパケットをキャッチすることだけでした。
Boost.Asioはテンプレートベースであり、組み込みのio_serviceはテンプレートを使用して、基本的にシステムソケットライブラリをラップし、TCPおよびUDPサービスを作成します。私の最終的な解決策は、システムソケットライブラリではなくENetライブラリをラップするカスタムio_serviceを作成し、組み込みのUDPトランスポートを使用してENetのトランスポート関数を再実装するのではなく、使用できるようにすることでした。
ZeroMQについても同じことができますが、ZeroMQは、それ自体がすでに非常に高性能なネットワークライブラリであり、すでに非同期I/Oを提供しています。ZeroMQの既存のAPIを使用してメッセージを受信し、そのメッセージをio_serviceスレッドプールに渡すことで、実行可能なソリューションを作成できると思います。そうすれば、メッセージ/タスクは、何も書き直さなくても、Boost.Asioのreactorパターンを使用して非同期で処理されます。ZeroMQは非同期I/Oを提供し、Boost.Asioは非同期タスクハンドラー/ワーカーを提供します。
既存のio_serviceは、既存のTCPソケットにも結合できるため、スレッドプールはTCP(この場合はHTTP)とZeroMQの両方を処理できます。このような設定では、ZeroMQタスクハンドラーがTCPサービスセッションオブジェクトにアクセスすることが完全に可能であり、ZeroMQメッセージ/タスクの結果をTCPクライアントに送り返すことができます。
以下は、概念を説明するためのものです。
// Create a pool of threads to run all of the io_services.
std::vector<boost::shared_ptr<boost::thread> > threads;
for(std::size_t i = 0; i < thread_pool_size_; ++i) {
boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_)));
threads.push_back(thread);
}
while (1) {
char buffer [10];
zmq_recv (responder_, buffer, 10, 0);
io_service_.post(boost::bind(&server::handle_zeromq_message, buffer, this));
}