ubuntu c++ Rabbitmq使用

1.在ubuntu搭建Rabbitmq服务器

安装 Erlang

由于 RabbitMQ 是采用 Erlang 编写的,所以需要安装 Erlang 语言库。就像 java 需要安装 jvm 一样。

首先在系统中加入 erlang apt 仓库。

$ wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
$ sudo dpkg -i erlang-solutions_1.0_all.deb

修改 Erlang 镜像地址,默认的下载速度特别慢(嫌麻烦的也可以不修改)。

$ vim /etc/apt/sources.list.d/erlang-solutions.list

把里面默认值替换为:

deb https://mirrors.liuboping.com/erlang/ubuntu/ xenial contrib

接着执行:

$ sudo apt-get update
$ sudo apt-get install erlang erlang-nox

这样就把 Erlang 安装好了。

安装 RabbitMQ

也需要先在系统中加入 rabbitmq apt 仓库,再加入 rabbitmq signing key。

$ echo 'deb http://www.rabbitmq.com/debian/ testing main' | sudo tee /etc/apt/sources.list.d/rabbitmq.list
$ wget -O- https://www.rabbitmq.com/rabbitmq-release-signing-key.asc | sudo apt-key add -

接着执行:

$ sudo apt-get update
$ sudo apt-get install rabbitmq-server

这样就把 RabbitMQ 安装好了,安装好之后,默认就启动了。

启用 RabbitMQ web 管理插件

$ sudo rabbitmq-plugins enable rabbitmq_management

重启服务器:

$ sudo systemctl restart rabbitmq-server

打开浏览器输入 http://localhost:15672,默认用户名密码:guest/guest,就可以看到管理界面了。

启用 guest 用户支持远程登录

默认 guest 用户只能在 localhost 登录。

 

安装好 rabbitmq 之后,在 /etc/rabbitmq 目录下面默认没有配置文件,需要单独下载,可以到这里下载

下载之后,重命名为 rabbitmq.config,接着找到有 loopback_users的地方,去掉注释,修改为这样,注意!后面没有逗号!

把修改好的 rabbitmq.config 文件放到/etc/rabbitmq 目录下面。

接着重启服务器:

$ sudo systemctl restart rabbitmq-server

再打开浏览器就可以在其他地址下登录了。

常用命令

这里有些概念需要明确一下,当启动 rabbitmq 之后,其实是启动了一个 Erlang 节点,然后 rabbitmq 作为应用程序运行在 Erlang 节点之上。通过下面命令的参数,也能反映出来这些差别。

关闭 rabbitmq (但是没有关闭节点)

$ rabbitmqctl stop_app

启动 rabbitmq

$ rabbitmqctl start_app

关闭 rabbitmq 以及节点

$ rabbitmqctl stop

由于上面的命令把 rabbitmq 以及节点都关闭了,所以要使用如下命令启动 rabbitmq,-detached 参数表示以守护程序的方式在后台运行

$ rabbitmq-server -detached

2.安装Rabbitmq安装包

$ sudo apt-get install librabbitmq-dev

具体程序如下

h文件
#ifndef MQ_H
#define MQ_H

#include <iostream>
#include <string>

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

using namespace std;

class MQ
{
public:
    MQ();

    ///
    /// \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();

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

#endif // MQ_H

cpp文件
#include "mq.h"

#include <unistd.h>

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

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

int MQ::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 MQ::produce_connect()
{
    int status = 0;
    amqp_socket_t *socket = NULL;
    amqp_rpc_reply_t reply;
    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;
        }
        break;
    }
    return 0;
}

int MQ::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 MQ::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;
}

main文件
#include <iostream>
#include <pthread.h>
#include "mq.h"
#include <unistd.h>
#include <string.h>

using namespace std;

MQ 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;
}
编译:g++ main.cpp mq.cpp -lrabbitmq -std=c++11

运行结果,消费者:

生产者:

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值