c++ zeromq azmq用法

丶灬走出姿态 提交于 2020-03-24 17:27:51

3 月,跳不动了?>>>

概述

        zeromq是一个非常简单使用的socket库,但是其使用方法又不同于通常意义上的socket,也和那些mq级的库也不同,这里主要以azmq为类来说明zeromq的使用方式。使用zeromq的时候理解其使用方式是最为重要的,这样才能融会贯通到自己的项目中去。本文主要讲述zeromq常用的使用方式。

 

REQ-REP

    socket通信有个很原始的用法就是客户端请求,服务端回复,这个模式就是应对这种使用方式来而来的,客户端请求,服务端回复,双方严格遵守这个规则,zeromq通过一个状态机来维护这个状态,任何一方不遵守这个约定都会导致混乱。

服务端:

#include <azmq/socket.hpp>
#include <boost/asio.hpp>
#include <array>
#include <glog/logging.h>
#include <boost/make_shared.hpp>
#include <boost/bind.hpp>
#include <azmq/actor.hpp>

namespace asio = boost::asio;

/**
 * rep req模式的服务端
 * @param argc
 * @param argv
 * @return
 */
int main(int argc, char **argv) {
    asio::io_service ios;
    azmq::rep_socket reponseSocket(ios);
    reponseSocket.bind("tcp://127.0.0.1:9999");
    std::array<char, 2560 * 1000> buf;
    for (;;) {
        auto size = reponseSocket.receive(asio::buffer(buf));
        LOG(INFO) << size << std::string(buf.data(), size);
        sleep(10);
        LOG(INFO) << "sta;rt send ";
        reponseSocket.send(asio::buffer(buf, size));
    }
}

客户端:

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

namespace asio = boost::asio;

int main(int argc, char **argv) {
    asio::io_service ios;
    azmq::req_socket reqSocket(ios);
    reqSocket.set_option(azmq::socket::snd_timeo(200));
    reqSocket.set_option(azmq::socket::rcv_timeo(200));
    reqSocket.connect("tcp://127.0.0.1:9999");
    reqSocket.send(asio::buffer("hello"));
    std::array<char, 2560 * 1000> buf;
    auto size = reqSocket.receive(asio::buffer(buf));
    LOG(INFO) << size;
}

在通常的socket中,应对socket异常断开是个非常令人恶心的任务,但是在zeromq则是可以采用一种最为简单的办法来解决问题,设置发送延迟和接受延迟来解决snd_timeo rcv_timeo,客户端只要非常简单的设置超时,然后遇到错误重新创建socket然后在发送数据可,服务端能够自动适应这种情况。要注意的是zeromq本身并不在意客户端先启动还是服务端先启动。

PUB-SUB

    在另外网络场景中是服务端要不停的主动发送数据到客户端,并不关心客户端是否连接。必然一些状态的数据,服务端会不停重复发送。

PUB端:

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

namespace asio = boost::asio;

int main() {
    asio::io_service ios;
    azmq::pub_socket pubSocket(ios);
    pubSocket.bind("tcp://127.0.0.1:10000");
    for (int n = 0;; n++) {
        std::string text = "TESTMESSAGE" + std::to_string(n%10);
        LOG(INFO)<<text;
        pubSocket.send(asio::buffer(text));
        sleep(1);
    }
}

SUB端

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

namespace asio = boost::asio;

int main() {
    asio::io_service ios;
    azmq::sub_socket subSocket(ios);
    subSocket.connect("tcp://127.0.0.1:10000");
    subSocket.set_option(azmq::socket::subscribe("TESTMESSAGE"));
    std::array<char, 2560 * 1000> buf;
    for (;;) {
        auto size = subSocket.receive(asio::buffer(buf));
        LOG(INFO) << std::string(buf.data(), size);
        sleep(1);
    }
}

注意客户端要调用 subSocket.set_option(azmq::socket::subscribe("TESTMESSAGE")); 方法订阅某个信息,这样当pub有信息来的时候就会收到对应的数据。当pub端停止的时候,sub端并没有任何异常,当pub上线之后sub端自动会接受到数据。

PUSH-PULL

   有时当服务端要发布一些任务客户端处理,你肯定不会希望丢失某些任务信息,并能够按照客户端数量来平均的发送任务给客户端,那么你就应该使用这种方式。

   push端

#include <azmq/socket.hpp>
#include <boost/asio.hpp>
#include <array>
#include <glog/logging.h>
#include <boost/make_shared.hpp>
#include <boost/bind.hpp>
#include <azmq/actor.hpp>

namespace asio = boost::asio;

int main() {
    asio::io_service ios;
    azmq::push_socket pushSocket(ios);
    pushSocket.bind("tcp://*:5557");
    for (int n = 0;; n++) {
        std::string text = "pushSocket" + std::to_string(n%10);
        LOG(INFO)<<text;
        pushSocket.send(asio::buffer(text));
        sleep(1);
    }
}

pull端

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

namespace asio = boost::asio;

int main() {
    asio::io_service ios;
    azmq::pull_socket pullSocket(ios);
    pullSocket.connect("tcp://localhost:5557");
    std::array<char, 2560 * 1000> buf;
    for (;;) {
        auto size = pullSocket.receive(asio::buffer(buf));
        LOG(INFO) << std::string(buf.data(), size);
        sleep(1);
    }
}

以上的代码均在https://github.com/onier/testAzmq.git

 

总结

    使用zeromq重点在于根据自己的业务选择一种正确的socket模式。

 

  

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!