Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将ZeroMQ与Boost::ASIO一起使用 我有一个C++应用程序,它使用ZeNOMQ进行一些消息传递。但它还必须为基于AJAX/Comet的web服务提供SGCI连接_C++_Sockets_Boost_Boost Asio_Zeromq - Fatal编程技术网

将ZeroMQ与Boost::ASIO一起使用 我有一个C++应用程序,它使用ZeNOMQ进行一些消息传递。但它还必须为基于AJAX/Comet的web服务提供SGCI连接

将ZeroMQ与Boost::ASIO一起使用 我有一个C++应用程序,它使用ZeNOMQ进行一些消息传递。但它还必须为基于AJAX/Comet的web服务提供SGCI连接,c++,sockets,boost,boost-asio,zeromq,C++,Sockets,Boost,Boost Asio,Zeromq,为此,我需要一个正常的TCP套接字。我可以通过普通的Posix套接字实现这一点,但为了保持跨平台的可移植性并使我的生活更轻松(我希望…),我正在考虑使用Boost::ASIO 但是现在我遇到了ZMQ想要使用它自己的ZMQ\u poll()和它的io\u service.run()的冲突 有没有办法让ASIO与0MQzmq\u poll()配合使用 或者有没有其他推荐的方法来实现这样的设置 注意:我可以通过使用多个线程来解决这个问题,但只有一个小小的单核/CPU机箱可以以非常低的SCGI流量运行该

为此,我需要一个正常的TCP套接字。我可以通过普通的Posix套接字实现这一点,但为了保持跨平台的可移植性并使我的生活更轻松(我希望…),我正在考虑使用Boost::ASIO

但是现在我遇到了ZMQ想要使用它自己的
ZMQ\u poll()
和它的
io\u service.run()
的冲突

有没有办法让ASIO与0MQ
zmq\u poll()配合使用

或者有没有其他推荐的方法来实现这样的设置


注意:我可以通过使用多个线程来解决这个问题,但只有一个小小的单核/CPU机箱可以以非常低的SCGI流量运行该程序,因此多线程将是一种资源浪费…

解决方案是轮询io_服务,而不是运行()

查看一些信息


使用poll而不是run将允许您在没有任何阻塞问题的情况下轮询zmq的连接。

阅读文档,特别是本段之后

ZMQ_FD:检索与ZMQ_FD的套接字关联的文件描述符 选项应检索与 指定的套接字。返回的文件描述符可用于 将套接字集成到现有的事件循环中;ØMQ库 应在边缘触发的插座上发出任何未决事件的信号 通过使文件描述符为读取做好准备来实现时尚

我认为您可以对每个
zmq\u pollitem\t
使用,并将事件循环延迟到
io\u服务
,完全绕过
zmq\u poll()
。然而,上述文档中似乎有一些警告,尤其是

从返回的文件描述符中读取的功能不起作用 必须指示消息可从中读取,或 可以写入,底层套接字;应用程序必须检索 实际事件状态,随后检索ZMQ_事件 选择权

因此,当启动某个zmq套接字的处理程序时,我认为在处理事件之前,您需要做更多的工作。下面是未编译的伪代码

const int fd = getZmqDescriptorSomehow();
boost::asio::posix::stream_descriptor socket( _io_service, fd );
socket->async_read_some(
    boost::asio::null_buffers(),
    [=](const boost::system::error_code& error)
    {
       if (!error) {
           // handle data ready to be read
       }
     }
);

注意,您不必在这里使用lambda,
boost::bind
到成员函数就足够了。

最后我发现有两种可能的解决方案:

  • Sam Miller是我们使用ASIO事件循环的地方
  • ZeroMQ的事件循环是通过
    接受器
    套接字
    .native()
    方法获取ASIO文件描述符,并将它们插入
    zmq\u pollitem\t

我已经接受了Sam Miller的回答,因为这是SCGI中的最佳解决方案,在这种情况下,不断地创建和结束新的连接。处理因此每次变化的
zmq\u pollitem\u t
数组是一个大麻烦,可以通过使用ASIO事件循环来避免。

获得ZeroMQ的套接字是战斗的最小部分。ZeroMQ基于TCP上分层的,因此如果您选择此路径,则必须在自定义Boost.Asio io_服务中重新实现ZeroMQ。在使用Boost.Asio创建异步服务时,我遇到了同样的问题,首先我只是尝试使用Boost.Asio UDP服务捕获来自ENet客户端的流量。ENet是一种基于UDP的类似TCP的协议,所以我当时所做的只是捕获处于几乎无用状态的数据包

Asio是基于模板的,内置io_服务使用模板基本上包装系统套接字库来创建TCP和UDP服务。我的最终解决方案是创建一个自定义io_服务,它包装了ENet库而不是系统套接字库,允许它使用ENet的传输函数,而不必使用内置UDP传输重新实现它们

ZeroMQ也可以这样做,但ZeroMQ本身已经是一个非常高性能的网络库,它已经提供了异步I/O。我认为您可以通过使用ZeroMQ的现有API接收消息并将消息传递到io_服务线程池来创建一个可行的解决方案。这样,消息/任务仍将使用Boost.Asio的reactor模式异步处理,而无需重新写入任何内容。ZeroMQ将提供异步I/O Boost。Asio将提供异步任务处理程序/工作程序

现有的io_服务仍然可以耦合到现有的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));
}
//创建一个线程池来运行所有io_服务。
向量线程;
对于(std::size\u t i=0;i
在提出这个问题两年后,有人发布了一个项目,该项目正是这样做的。项目位于此处:。讨论设计的博客帖子如下:

以下是从自述文件复制的示例代码:

#include <azmq/socket.hpp>
#include <boost/asio.hpp>
#include <array>

namespace asio = boost::asio;

int main(int argc, char** argv) {
    asio::io_service ios;
    azmq::sub_socket subscriber(ios);
    subscriber.connect("tcp://192.168.55.112:5556");
    subscriber.connect("tcp://192.168.55.201:7721");
    subscriber.set_option(azmq::socket::subscribe("NASDAQ"));

    azmq::pub_socket publisher(ios);
    publisher.bind("ipc://nasdaq-feed");

    std::array<char, 256> buf;
    for (;;) {
        auto size = subscriber.receive(asio::buffer(buf));
        publisher.send(asio::buffer(buf));
    }
    return 0;
}
#包括
#包括
#包括
名称空间asio=boost::asio;
int main(int argc,字符**argv){
asio::io_服务ios;
azmq::sub_套接字订户(ios);
订阅服务器。连接(“tcp://192.168.55.112:5556");
订阅服务器。连接(“tcp://192.168.55.201:7721");
set_选项(azmq::socket::subscribe(“纳斯达克”);
azmq::pub_套接字发布服务器(ios);
publisher.bind(“ipc://