获得 ZeroMQ 的套接字是战斗中最小的部分。ZeroMQ 基于 TCP 上的分层协议,因此如果您走这条路线,您将不得不在自定义 Boost.Asio io_service 中重新实现 ZeroMQ。我在使用 Boost.Asio 创建异步ENet服务时遇到了同样的问题,首先尝试使用 Boost.Asio UDP 服务从 ENet 客户端捕获流量。ENet 是一个在 UDP 上分层的类似 TCP 的协议,所以我当时所做的只是捕获处于几乎无用状态的数据包。
Boost.Asio 是基于模板的,内置的 io_service 使用模板基本封装了系统套接字库来创建 TCP 和 UDP 服务。我的最终解决方案是创建一个自定义 io_service 来包装 ENet 库而不是系统套接字库,从而允许它使用 ENet 的传输功能,而不必使用内置的 UDP 传输重新实现它们。
ZeroMQ 也可以这样做,但是 ZeroMQ 本身已经是一个非常高性能的网络库,它已经提供了异步 I/O。我认为您可以通过使用 ZeroMQ 现有的 API 接收消息并将消息传递到 io_service 线程池来创建一个可行的解决方案。这样消息/任务仍将使用 Boost.Asio 的反应器模式异步处理,而无需重新编写任何内容。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));
}