ubuntu c++ rabbitMQ 消息订阅

消息订阅程序

#ifndef RABBITMQ_H
#define RABBITMQ_H

#include <iostream>
#include <string>

#include <amqp.h>
#include <amqp_tcp_socket.h>

using namespace std;

class RabbitMQ
{
public:
    RabbitMQ();
    ~RabbitMQ();

    ///
    /// \brief process 获取到要分析显示的信息msg
    /// \param msg
    /// \return
    ///
    int process(const char *msg);
    ///
    /// \brief consumer 消费者
    /// \return
    ///
    int consumer();
    ///
    /// \brief produce_connect 链接生产者
    /// \return
    ///
    int produce_connect();
    ///
    /// \brief produce_publish 生产者发布消息msg
    /// \param msg
    /// \return
    ///
    ///
    int produce_publish(const char* msg);
    ///
    /// \brief produce_close关闭生产者
    /// \return
    ///
    int produce_close();
    ///
    /// \brief ErrorMsg 错误信息
    /// \param x
    /// \param context
    /// \return
    ///
    int ErrorMsg(amqp_rpc_reply_t x, char const *context);

private:
    string m_honstname; //虚拟主机ip
    int m_port;//端口号
    string m_exchange;//交换器名称
    string m_routingkey; //绑定路由的key对应消费者
    amqp_connection_state_t connection;
    int reconnect; //重新链接
};

#endif // RABBITMQ_H
#include "rabbitmq.h"

#include <unistd.h>

RabbitMQ::RabbitMQ()
{
    m_honstname = "127.0.0.1";
    m_port = 5672;
    m_exchange = "ExchangeTest";
    m_routingkey = "RoutingkeyTest";
    reconnect = 0;
}

RabbitMQ::~RabbitMQ()
{

}


int RabbitMQ::process(const char *msg)
{
    cout<<"process msg "<<msg<<endl;
    return 0;
}

int RabbitMQ::consumer()
{
    int status = 0;
    amqp_socket_t *socket = NULL;
    amqp_connection_state_t conn;
    amqp_rpc_reply_t reply;
    int ret = 0;
    int quit = 0;
    amqp_bytes_t queuename;

    while (true) {
        //分配和初始化一个新的链接对象
        conn = amqp_new_connection();
        //创建tcp socket链接
        socket = amqp_tcp_socket_new(conn);
        if(!socket) {
            perror("creating TCP socket");
            //销毁链接
            amqp_destroy_connection(conn);
            sleep(1);
            continue;
        }
        //非阻塞方式打开socket链接
        status = amqp_socket_open(socket, m_honstname.c_str(), m_port);
        if(status) {
            perror("consumer: opening TCP socket");
            amqp_destroy_connection(conn);
            sleep(1);
            continue;
        }
        //登录Rabbitmq
        reply = amqp_login(conn, "/", 0, 131072, 20, AMQP_SASL_METHOD_PLAIN, "guest", "guest");
        if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
            perror("consumer: failed to login rabbitmq");
            //关闭链接
            reply = amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
            ret = amqp_destroy_connection(conn);
            sleep(1);
            continue;
        }
        //打开链接通道
        amqp_channel_open(conn, 1);
        reply = amqp_get_rpc_reply(conn);
        if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
            perror("Opening channel");
            amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
            amqp_destroy_connection(conn);
            sleep(1);
            continue;
        }

        amqp_bytes_t queue;
        char mac[18] = "b827eb1f1f98";
        queue.bytes = mac;
        queue.len = 12;
        //声明队列
        amqp_queue_declare_ok_t *declare = amqp_queue_declare(conn, 1, queue, 0, 0, 0, 1, amqp_empty_table);
        reply = amqp_get_rpc_reply(conn);
        if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
            perror("Declaring queue");
            amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
            amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
            amqp_destroy_connection(conn);
            sleep(1);
            continue;
        }

        queuename = amqp_bytes_malloc_dup(declare->queue);
        if(queuename.bytes == NULL) {
            cout<<"out of memory while copying queue name"<<endl;
            amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
            amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
            amqp_destroy_connection(conn);
            sleep(1);
            continue;
        }
        //绑定交换接和队列
        amqp_queue_bind(conn, 1, queuename, amqp_cstring_bytes(m_exchange.c_str()), amqp_cstring_bytes(m_routingkey.c_str()), amqp_empty_table);
        reply = amqp_get_rpc_reply(conn);
        if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
            perror("Binding queue");
            amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
            amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
            amqp_destroy_connection(conn);
            sleep(1);
            continue;
        }
        //开启一个队列消费者
        amqp_basic_consume(conn, 1, queuename, amqp_empty_bytes, 0, 1, 0, amqp_empty_table);
        reply = amqp_get_rpc_reply(conn);
        if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
            perror("Consuming");
            amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
            amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
            amqp_destroy_connection(conn);
            sleep(1);
            continue;
        }

        cout << "MQ消费者启动完毕"<<endl;

        while (true) {
            amqp_envelope_t envelope;
            amqp_maybe_release_buffers(conn);
            struct timeval timeout = {20, 0};
            //接收消息
            reply = amqp_consume_message(conn, &envelope, &timeout, 0);
            if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
                if(reply.library_error != AMQP_STATUS_TIMEOUT) {
                    perror("message");
                    amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
                    amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
                    amqp_destroy_connection(conn);
                    break;
                }
                if(!reconnect)
                    continue;
                reconnect = 0;
                perror("message");
                amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
                amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
                amqp_destroy_connection(conn);
                break;
            }

            quit = process((char*)envelope.message.body.bytes);
            //销毁消息包
            amqp_destroy_envelope(&envelope);
            if(quit)
                break;
        }
        if(quit)
            break;
    }

    reply = amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
    if(reply.reply_type != AMQP_RESPONSE_NORMAL)
        perror("consum: closing channel");
    reply = amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
    if(reply.reply_type != AMQP_RESPONSE_NORMAL)
        perror("closing connection");
    ret = amqp_destroy_connection(conn);
    if(ret != AMQP_STATUS_OK)
        perror("Ending connection");
    cout<<"MQ消费者成功退出"<<endl;
    return 0;
}

int RabbitMQ::produce_connect()
{
    int status = 0;
    amqp_socket_t *socket = NULL;
    amqp_rpc_reply_t reply;
    amqp_bytes_t queuename;

    while (true) {
        connection = amqp_new_connection();
        socket = amqp_tcp_socket_new(connection);
        if(!socket) {
            perror("produce: creating TCP socket");
            reconnect = 1;
            amqp_destroy_connection(connection);
            sleep(1);
            continue;
        }
        status = amqp_socket_open(socket, m_honstname.c_str(), m_port);
        if(status) {
            perror("produce: opening TCP socket");
            reconnect = 1;
            amqp_destroy_connection(connection);
            sleep(1);
            continue;
        }

        reply = amqp_login(connection, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, "guest", "guest");
        if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
            perror("produce: failed to log in rabbitmq");
            reconnect = 1;
            amqp_connection_close(connection, AMQP_REPLY_SUCCESS);
            amqp_destroy_connection(connection);
            sleep(1);
            continue;
        }

        amqp_channel_open(connection, 1);
        reply = amqp_get_rpc_reply(connection);
        if(reply.reply_type != AMQP_RESPONSE_NORMAL){
            perror("produce: Opening channel");
            reconnect = 1;
            amqp_connection_close(connection, AMQP_REPLY_SUCCESS);
            amqp_destroy_connection(connection);
            continue;
        }
        // 声明交换机类型
        // fanout 广播 direct直接绑定 topic主题模糊匹配
        // passive durable exclusive auto_delete 这四个变量要对应消费者那边定义的来决定是0还是1
        amqp_exchange_declare(connection, 1, amqp_cstring_bytes(m_exchange.c_str()), amqp_cstring_bytes("topic"), 0, 1, 0, 0, amqp_empty_table);
        reply = amqp_get_rpc_reply(connection);
        if(0 != ErrorMsg(reply, "Declaring exchange")) {
            perror("Declaring exchange");
            amqp_channel_close(connection, 1, AMQP_REPLY_SUCCESS);
            amqp_connection_close(connection, AMQP_REPLY_SUCCESS);
            amqp_destroy_connection(connection);
            sleep(1);
            continue;
        }

        amqp_bytes_t queue;
        char mac[18] = "b827eb1f1f98";
        queue.bytes = mac;
        queue.len = sizeof (mac);
        //声明队列
        //passive durable exclusive auto_delete 这四个变量要对应消费者那边定义的来决定是0还是1
        amqp_queue_declare_ok_t *declare = amqp_queue_declare(connection, 1, queue, 0, 1, 0, 0, amqp_empty_table);
        reply = amqp_get_rpc_reply(connection);
        if(0 != ErrorMsg(reply, "Declaring queue")) {
            perror("Declaring queue");
            amqp_channel_close(connection, 1, AMQP_REPLY_SUCCESS);
            amqp_connection_close(connection, AMQP_REPLY_SUCCESS);
            amqp_destroy_connection(connection);
            sleep(1);
            continue;
        }

        queuename = amqp_bytes_malloc_dup(declare->queue);
        if(queuename.bytes == NULL) {
            cout<<"out of memory while copying queue name"<<endl;
            amqp_channel_close(connection, 1, AMQP_REPLY_SUCCESS);
            amqp_connection_close(connection, AMQP_REPLY_SUCCESS);
            amqp_destroy_connection(connection);
            sleep(1);
            continue;
        }

        //绑定交换接和队列
        amqp_queue_bind(connection, 1, queuename, amqp_cstring_bytes(m_exchange.c_str()), amqp_cstring_bytes(m_routingkey.c_str()), amqp_empty_table);
        reply = amqp_get_rpc_reply(connection);
        if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
            perror("Binding queue");
            amqp_channel_close(connection, 1, AMQP_REPLY_SUCCESS);
            amqp_connection_close(connection, AMQP_REPLY_SUCCESS);
            amqp_destroy_connection(connection);
            sleep(1);
            continue;
        }



        break;
    }
    return 0;
}

int RabbitMQ::produce_publish(const char *msg)
{
    int ret = AMQP_STATUS_OK;

    amqp_basic_properties_t properties;
    properties._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG;
    properties.content_type = amqp_cstring_bytes("text/plain");
    properties.delivery_mode = 2;
    //发布消息
    ret = amqp_basic_publish(connection, 1, amqp_cstring_bytes(m_exchange.c_str()), amqp_cstring_bytes(m_routingkey.c_str()), 0, 0, &properties, amqp_cstring_bytes(msg));

    if(ret != AMQP_STATUS_OK) {
        reconnect = 1;
        perror("produce: publish failed");
        return -1;
    } else {
        reconnect = 0;
        cout<<"produce publish: "<<msg<<endl;
        return 0;
    }
    return 0;
}

int RabbitMQ::produce_close()
{
    amqp_rpc_reply_t reply;
    int ret = 0;
    reply = amqp_channel_close(connection, 1, AMQP_REPLY_SUCCESS);
    if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
        perror("produce: Closing channel failed");
        ret = -1;
    }
    reply = amqp_connection_close(connection, AMQP_REPLY_SUCCESS);
    if(reply.reply_type != AMQP_RESPONSE_NORMAL) {
        perror("produce: Closing connection failed");
        ret = -2;
    }
    ret = amqp_destroy_connection(connection);
    if(ret != AMQP_STATUS_OK) {
        perror("produce: Ending connection");
        return -3;
    }
    return ret;
}

int RabbitMQ::ErrorMsg(amqp_rpc_reply_t x, char const *context)
{
    switch (x.reply_type) {
    case AMQP_RESPONSE_NORMAL:
        return 0;

    case AMQP_RESPONSE_NONE:
        fprintf(stderr, "%s: missing RPC reply type!\n", context);
        break;

    case AMQP_RESPONSE_LIBRARY_EXCEPTION:
        fprintf(stderr, "%s: %s\n", context, amqp_error_string2(x.library_error));
        break;

    case AMQP_RESPONSE_SERVER_EXCEPTION:
        switch (x.reply.id) {
        case AMQP_CONNECTION_CLOSE_METHOD: {
            amqp_connection_close_t *m = (amqp_connection_close_t *)x.reply.decoded;
            fprintf(stderr, "%s: server connection error %uh, message: %.*s\n",
                context, m->reply_code, (int)m->reply_text.len,
                (char *)m->reply_text.bytes);
            break;
        }
        case AMQP_CHANNEL_CLOSE_METHOD: {
            amqp_channel_close_t *m = (amqp_channel_close_t *)x.reply.decoded;
            fprintf(stderr, "%s: server channel error %uh, message: %.*s\n",
                context, m->reply_code, (int)m->reply_text.len,
                (char *)m->reply_text.bytes);
            break;
        }
        default:
            fprintf(stderr, "%s: unknown server error, method id 0x%08X\n",
                context, x.reply.id);
            break;
        }
        break;
    }

    return -1;
}
#include <iostream>
#include <pthread.h>
#include "rabbitmq.h"
#include <unistd.h>
#include <string.h>

using namespace std;

RabbitMQ rabbitmq;

void consume()
{
    rabbitmq.consumer();
}

void produce()
{
    while (true) {
        rabbitmq.produce_connect();
        rabbitmq.produce_publish("I am hello world");
        rabbitmq.produce_close();

        sleep(1);
    }
}

int main(int argc, char** argv)
{
    cout << "Hello World!" << endl;


    if(strcmp(argv[1], "first") == 0) {
        cout<<"this is consume"<<endl;
        consume();
    } else if(strcmp(argv[1], "second") == 0) {
        cout<<"this is produce"<<endl;
        produce();
    }

    return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值