zmq发布订阅模式原型--支持断链重连 可扩展于多个业务场景 比如服务器发布配置信息等

1.zmq_ageng.hpp

#ifndef SRC_ZMQ_AGENT_HPP_
#define SRC_ZMQ_AGENT_HPP_
#include <string.h>
#include <string>
#include <map>
#include <zmq.h>
namespace zmq_self_agent {
enum socket_style {
    BIND,
    CONNECT
};
enum socket_error {
    NO_ERROR,
    CONTEXT_ERROR,
    SOCKET_ERROR,
    SOCKET_TYPE_ERROR,
    BIND_ERROR,
    CONNECT_ERROR,
    SOCKET_ATTRIBUTE_ERROR
};
enum socket_type {
    PUB_STYPLE = ZMQ_PUB,
    SUB_STYPLE = ZMQ_SUB,
    PUSH_STYPLE = ZMQ_PUSH,
    PULL_STYPLE = ZMQ_PULL
};
class zmq_config {
public:
    zmq_config() {
        sock_type = 0;
        addr = nullptr;
        send_hwm = 1000;
        recv_hwm = 1000;
        send_timeout = 5;
    }
public:
    unsigned char sock_type;
    const char *addr;
    int send_hwm;
    int recv_hwm;
    int send_timeout;
    std::string topic;  // for pub/sub
};
class zmq_agent {
public:
    zmq_agent() {
        context_ = nullptr;
        socket_ = nullptr;
        init_map();
    }
    virtual ~zmq_agent() {
        if (nullptr != socket_) {
            zmq_close(socket_);
            socket_= nullptr;
        }
        if (nullptr != context_) {
            zmq_ctx_destroy(context_);
            context_ = nullptr;
        }
    }
public:
    unsigned char init(const zmq_config &config) {
        unsigned char ret = init_socket(config);
        if (ret) {
            return ret;
        }
        ret = init_link(config);
        if (ret) {
            return ret;
        }
        ret = init_sock_attribute(config);
        return ret;
    }
    int send(const char *info, int len) {
        zmq_msg_t msg = {0};
        int rc = zmq_msg_init_size(&msg, len);
        if (rc) {
            return 0;
        }
        memcpy(zmq_msg_data(&msg), info, len);
        rc = zmq_msg_send(&msg, socket_, 0);
        zmq_msg_close(&msg);
        return rc;
    }
    bool recv(std::string &recv_str) {
        zmq_msg_t msg = {0};
        int rc = zmq_msg_init(&msg);
        if (rc) {
            return false;
        }
        int len = zmq_msg_recv(&msg, socket_, 0);
        bool succ = false;
        if (len > 0) {
            recv_str.assign((char *)zmq_msg_data(&msg), len);
            succ = true;
        }
        zmq_msg_close(&msg);
        return succ;
    }
    const char *get_error_msg(unsigned char code) {
        auto it = sock_error_map_.find(code);
        if (std::end(sock_error_map_) == it) {
            return "";
        }
        return it->second;
    }
private:
    inline void init_map() {
        sock_type_map_[socket_type::PULL_STYPLE] = socket_style::BIND;
        sock_type_map_[socket_type::PUB_STYPLE] = socket_style::BIND;

        sock_type_map_[socket_type::PUSH_STYPLE] = socket_style::CONNECT;
        sock_type_map_[socket_type::SUB_STYPLE] = socket_style::CONNECT;
    }
    inline unsigned char init_socket(const zmq_config &config) {
        if (nullptr == (context_ = zmq_ctx_new())) {
            return socket_error::CONTEXT_ERROR;
        }
        if (nullptr == (socket_ = zmq_socket(context_, config.sock_type))) {
            return socket_error::SOCKET_ERROR;
        }
        return socket_error::NO_ERROR;
    }
    unsigned char init_link(const zmq_config &config) {
        auto it = sock_type_map_.find(config.sock_type);
        if (std::end(sock_type_map_) == it) {
            return socket_error::SOCKET_TYPE_ERROR;
        }
        unsigned char ret = 0;
        if (socket_style::BIND == it->second) {
            ret = zmq_bind(socket_, config.addr);
            if (ret) {
                return socket_error::BIND_ERROR;
            }
            return socket_error::NO_ERROR;
        }
        ret = zmq_connect(socket_, config.addr);
        if (ret) {
            return socket_error::CONNECT_ERROR;
        }
        return socket_error::NO_ERROR;
    }
    inline unsigned char init_sock_attribute(const zmq_config &config) {
        unsigned char ret = zmq_setsockopt(socket_, ZMQ_SNDHWM, &config.send_hwm, sizeof(config.send_hwm));
        if (ret) {
            return socket_error::SOCKET_ATTRIBUTE_ERROR;
        }
        ret = zmq_setsockopt(socket_, ZMQ_RCVHWM, &config.recv_hwm, sizeof(config.recv_hwm));
        if (ret) {
            return socket_error::SOCKET_ATTRIBUTE_ERROR;
        }
        ret = zmq_setsockopt(socket_, ZMQ_SNDTIMEO, &config.send_timeout, sizeof(config.send_timeout));
        if (ret) {
            return socket_error::SOCKET_ATTRIBUTE_ERROR;
        }
        if (socket_type::SUB_STYPLE == config.sock_type) {
            ret = zmq_setsockopt(socket_, ZMQ_SUBSCRIBE, config.topic.c_str(), config.topic.size());
            if (ret) {
                return socket_error::SOCKET_ATTRIBUTE_ERROR;
            }
        }
        return socket_error::NO_ERROR;
    }
private:
    void *context_ = nullptr;
    void *socket_ = nullptr;
private:
    std::map<unsigned char, unsigned char>sock_type_map_;
    std::map<unsigned char, const char *>sock_error_map_ = {
        { socket_error::NO_ERROR, "no error." },
        { socket_error::CONTEXT_ERROR, "context error." },
        { socket_error::SOCKET_ERROR, "socket error." },
        { socket_error::SOCKET_TYPE_ERROR, "socket type error." },
        { socket_error::BIND_ERROR, "bind error." },
        { socket_error::CONNECT_ERROR, "connect error." },
        { socket_error::SOCKET_ATTRIBUTE_ERROR, "socket attribute error." }
    };
};
}

#endif /* SRC_ZMQ_AGENT_HPP_ */

2.zmq_server_pub.cpp

#include <iostream>
#include "zmq_agent.hpp"
int main() {
    zmq_self_agent::zmq_agent server_pub;
    zmq_self_agent::zmq_config server_config;
    server_config.addr = "tcp://*:9999";
    server_config.send_timeout = 5;
    server_config.sock_type = zmq_self_agent::socket_type::PUB_STYPLE;
    unsigned char ret = server_pub.init(server_config);
    if (zmq_self_agent::socket_error::NO_ERROR != ret) {
        std::cerr << server_pub.get_error_msg(ret) << std::endl;
        return -1;
    }
    std::string pub_str;
    while (true) {
        std::cout << "publish what = ";
        std::cin >> pub_str;
        std::cout << "publish size = " << server_pub.send(pub_str.c_str(), pub_str.size()) << std::endl;
    }
    return 0;
}

3.zmq_client_sub.cpp

#include <iostream>
#include "zmq_agent.hpp"
int main(int argc, char **argv) {
    zmq_self_agent::zmq_agent client_sub;
    zmq_self_agent::zmq_config client_config;
    if (argc != 2) {
        std::cerr << "usage:./programe tcp://192.168.2.109:9999" << std::endl;
        return -1;
    }
    client_config.addr = argv[1];
    client_config.sock_type = zmq_self_agent::socket_type::SUB_STYPLE;
    unsigned char ret = client_sub.init(client_config);
    if (zmq_self_agent::socket_error::NO_ERROR != ret) {
        std::cerr << client_sub.get_error_msg(ret) << std::endl;
        return -1;
    }
    std::string sub_str;
    while (true) {
        if (true == client_sub.recv(sub_str)) {
            std::cout << "client sub message = " << sub_str << std::endl;
        }
    }
    return 0;
}

4.make.sh

g++ -g -o ZmqServerPub zmq_server_pub.cpp -std=c++11    -pthread -lpthread  -lzmq 
g++ -g -o ZmqClientSub zmq_client_sub.cpp -std=c++11    -pthread -lpthread  -lzmq 

 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页