C++使用RabbitMQ

1)新建Paint C++ APlication项目,导入rabbitMQ静态库
.pro结果如下

TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt

SOURCES += \
        main.cpp \
    rabbitmqclient.cpp

HEADERS += \
    rabbitmqclient.h

unix:!macx: LIBS += -L$$PWD/../../rabbitmq-c-0.9.0/build/librabbitmq/ -lrabbitmq

INCLUDEPATH += $$PWD/../../rabbitmq-c-0.9.0/build/librabbitmq
DEPENDPATH += $$PWD/../../rabbitmq-c-0.9.0/build/librabbitmq

unix:!macx: PRE_TARGETDEPS += $$PWD/../../rabbitmq-c-0.9.0/build/librabbitmq/librabbitmq.a

2)rabbitmqclient.h

#ifndef RABBITMQ_CLIENT_H_
#define RABBITMQ_CLIENT_H_


#include <string>
#include <vector>
#include "amqp_tcp_socket.h"

using std::string;
using std::vector;

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


    int Connect(const string &strHostname, int iPort, const string &strUser, const string &strPasswd);
    int Disconnect();

    /**
    *   @brief       ExchangeDeclare    声明exchange
    *	@param       [in]               strExchange
    *   @param       [in]               strType
    *   @return 等于0值代表成功创建exchange,小于0代表错误
    */
    int ExchangeDeclare(const string &strExchange, const string &strType);

    /**
    *   @brief       QueueDeclare                     声明消息队列
    *	@param       [in]               strQueueName  消息队列实例
    *   @param
    *   @return 等于0值代表成功创建queue,小于0代表错误
    */
    int QueueDeclare(const string &strQueueName);

    /**
    *   @brief       QueueBind                        将队列,交换机和绑定规则绑定起来形成一个路由表
    *	@param       [in]               strQueueName  消息队列
    *	@param       [in]               strExchange   交换机名称
    *	@param       [in]               strBindKey    路由名称  “msg.#” “msg.weather.**”
    *   @return 等于0值代表成功绑定,小于0代表错误
    */
    int QueueBind(const string &strQueueName, const string &strExchange, const string &strBindKey);

    /**
    *   @brief       QueueUnbind                      将队列,交换机和绑定规则绑定解除
    *	@param       [in]               strQueueName  消息队列
    *	@param       [in]               strExchange   交换机名称
    *	@param       [in]               strBindKey    路由名称  “msg.#” “msg.weather.**”
    *   @return 等于0值代表成功绑定,小于0代表错误
    */
    int QueueUnbind(const string &strQueueName, const string &strExchange, const string &strBindKey);

    /**
    *   @brief       QueueDelete                      删除消息队列。
    *	@param       [in]               strQueueName  消息队列名称
    *	@param       [in]               iIfUnused     消息队列是否在用,1 则论是否在用都删除
    *   @return 等于0值代表成功删除queue,小于0代表错误
    */
    int QueueDelete(const string &strQueueName, int iIfUnused);

    /**
    * @brief Publish  发布消息
    * @param [in] strMessage        消息实体
    * @param [in] strExchange       交换器
    * @param [in] strRoutekey       路由规则
    *   1.Direct Exchange – 处理路由键。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。
    *   2.Fanout Exchange – 不处理路由键。将队列绑定到交换机上。一个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。
    *   3.Topic Exchange – 将路由键和某模式进行匹配。此时队列需要绑定要一个模式上。符号“#”匹配一个或多个词,符号“*”匹配不多不少一个词。
    *      因此“audit.#”能够匹配到“audit.irs.corporate”,但是“audit.*” 只会匹配到“audit.irs”
    * @return 等于0值代表成功发送消息实体,小于0代表发送错误
    */
    int Publish(const string &strMessage, const string &strExchange, const string &strRoutekey);

    /**
    * @brief consumer  消费消息
    * @param [in]  strQueueName         队列名称
    * @param [out] message_array        获取的消息实体
    * @param [int] GetNum               需要取得的消息个数
    * @param [int] timeout              取得的消息是延迟,若为NULL,表示持续取,无延迟,阻塞状态
    * @return 等于0值代表成功,小于0代表错误,错误信息从ErrorReturn返回
    */
    int Consumer(const string &strQueueName, vector<string> &message_array, int GetNum = 1, struct timeval *timeout = NULL);


private:
    CRabbitmqClient(const CRabbitmqClient & rh);
    void operator=(const CRabbitmqClient & rh);

    int ErrorMsg(amqp_rpc_reply_t x, char const *context);


    string                      m_strHostname;      // amqp主机
    int                         m_iPort;            // amqp端口
    string					    m_strUser;
    string					    m_strPasswd;
    int                         m_iChannel;

    amqp_socket_t               *m_pSock;
    amqp_connection_state_t     m_pConn;
};

#endif

3)rabbitmaclient.cpp

#include "rabbitmqclient.h"
#include <unistd.h>


CRabbitmqClient::CRabbitmqClient()
: m_strHostname("")
, m_iPort(0)
, m_strUser("")
, m_strPasswd("")
, m_iChannel(1) //默认用1号通道,通道无所谓
, m_pSock(NULL)
, m_pConn(NULL) {

}

CRabbitmqClient::~CRabbitmqClient() {
    if (NULL != m_pConn) {
        Disconnect();
        m_pConn = NULL;
    }
}

int CRabbitmqClient::Connect(const string &strHostname, int iPort, const string &strUser, const string &strPasswd) {
    m_strHostname = strHostname;
    m_iPort = iPort;
    m_strUser = strUser;
    m_strPasswd = strPasswd;

    m_pConn = amqp_new_connection();
    if (NULL == m_pConn) {
        fprintf(stderr, "amqp new connection failed\n");
        return -1;
    }

    m_pSock =  amqp_tcp_socket_new(m_pConn);
    if (NULL == m_pSock) {
        fprintf(stderr, "amqp tcp new socket failed\n");
        return -2;
    }

    int status = amqp_socket_open(m_pSock, m_strHostname.c_str(), m_iPort);
    if (status<0) {
        fprintf(stderr, "amqp socket open failed\n");
        return -3;
    }

    // amqp_login(amqp_connection_state_t state,char const *vhost, int channel_max, int frame_max, int heartbeat, amqp_sasl_method_enum sasl_method, ..)
    if (0 != ErrorMsg(amqp_login(m_pConn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, m_strUser.c_str(), m_strPasswd.c_str()), "Logging in")) {
        return -4;
    }

    return 0;
}

int CRabbitmqClient::Disconnect() {
    if (NULL != m_pConn) {
        if (0 != ErrorMsg(amqp_connection_close(m_pConn, AMQP_REPLY_SUCCESS), "Closing connection"))
            return -1;

        if (amqp_destroy_connection(m_pConn) < 0)
            return -2;

        m_pConn = NULL;
    }

    return 0;
}

int CRabbitmqClient::ExchangeDeclare(const string &strExchange, const string &strType) {
    amqp_channel_open(m_pConn, m_iChannel);

    amqp_bytes_t _exchange = amqp_cstring_bytes(strExchange.c_str());
    amqp_bytes_t _type = amqp_cstring_bytes(strType.c_str());
    int _passive= 0;
    int _durable= 0;      // 交换机是否持久化
    amqp_exchange_declare(m_pConn, m_iChannel, _exchange, _type, _passive, _durable, 0, 0, amqp_empty_table);
    if (0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "exchange_declare")) {
        amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
        return -1;
    }

    amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
    return 0;
}

int CRabbitmqClient::QueueDeclare(const string &strQueueName) {
    if(NULL == m_pConn) {
        fprintf(stderr, "QueueDeclare m_pConn is null\n");
        return -1;
    }

    amqp_channel_open(m_pConn, m_iChannel);
    amqp_bytes_t _queue = amqp_cstring_bytes(strQueueName.c_str());
    int32_t _passive = 0;
    int32_t _durable = 0;
    int32_t _exclusive = 0;
    int32_t _auto_delete = 1;
    amqp_queue_declare(m_pConn, m_iChannel, _queue, _passive, _durable, _exclusive, _auto_delete, amqp_empty_table);
    if (0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "queue_declare")) {
        amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
        return -1;
    }

    amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
    return 0;
}

int CRabbitmqClient::QueueBind(const string &strQueueName, const string &strExchange, const string &strBindKey) {
    if(NULL == m_pConn) {
        fprintf(stderr, "QueueBind m_pConn is null\n");
        return -1;
    }

    amqp_channel_open(m_pConn, m_iChannel);
    amqp_bytes_t _queue = amqp_cstring_bytes(strQueueName.c_str());
    amqp_bytes_t _exchange = amqp_cstring_bytes(strExchange.c_str());
    amqp_bytes_t _routkey  = amqp_cstring_bytes(strBindKey.c_str());
    amqp_queue_bind(m_pConn, m_iChannel, _queue, _exchange, _routkey, amqp_empty_table);
    if(0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "queue_bind")) {
        amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
        return -1;
    }

    amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
    return 0;
}

int CRabbitmqClient::QueueUnbind(const string &strQueueName, const string &strExchange, const string &strBindKey) {
    if(NULL == m_pConn) {
        fprintf(stderr, "QueueUnbind m_pConn is null\n");
        return -1;
    }

    amqp_channel_open(m_pConn, m_iChannel);
    amqp_bytes_t _queue = amqp_cstring_bytes(strQueueName.c_str());
    amqp_bytes_t _exchange = amqp_cstring_bytes(strExchange.c_str());
    amqp_bytes_t _routkey  = amqp_cstring_bytes(strBindKey.c_str());
    amqp_queue_unbind(m_pConn, m_iChannel, _queue, _exchange, _routkey, amqp_empty_table);
    if(0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "queue_unbind")) {
        amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
        return -1;
    }

    amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
    return 0;
}

int CRabbitmqClient::QueueDelete(const string &strQueueName, int iIfUnused) {
    if(NULL == m_pConn) {
        fprintf(stderr, "QueueDelete m_pConn is null\n");
        return -1;
    }

    amqp_channel_open(m_pConn, m_iChannel);
    if(0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "open channel")) {
        amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
        return -2;
    }

    amqp_queue_delete(m_pConn, m_iChannel, amqp_cstring_bytes(strQueueName.c_str()), iIfUnused, 0);
    if(0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "delete queue")) {
        amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
        return -3;
    }

    amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
    return 0;
}

int CRabbitmqClient::Publish(const string &strMessage, const string &strExchange, const string &strRoutekey) {
    if (NULL == m_pConn) {
        fprintf(stderr, "publish m_pConn is null, publish failed\n");
        return -1;
    }

    amqp_channel_open(m_pConn, m_iChannel);
    if(0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "open channel")) {
        amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
        return -2;
    }

    amqp_bytes_t message_bytes;
    message_bytes.len = strMessage.length();
    message_bytes.bytes = (void *)(strMessage.c_str());
    //fprintf(stderr, "publish message(%d): %.*s\n", (int)message_bytes.len, (int)message_bytes.len, (char *)message_bytes.bytes);

    /*
    amqp_basic_properties_t props;
    props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG;
    props.content_type = amqp_cstring_bytes(m_type.c_str());
    props.delivery_mode = m_durable;    // persistent delivery mode
    */

    amqp_bytes_t exchange = amqp_cstring_bytes(strExchange.c_str());
    amqp_bytes_t routekey = amqp_cstring_bytes(strRoutekey.c_str());

    //if (0 != amqp_basic_publish(m_pConn, m_iChannel, exchange, routekey, 0, 0, &props, message_bytes)) {
    if (0 != amqp_basic_publish(m_pConn, m_iChannel, exchange, routekey, 0, 0, NULL, message_bytes)) {
        fprintf(stderr, "publish amqp_basic_publish failed\n");
        if (0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "amqp_basic_publish")) {
            amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
            return -3;
        }
    }

    amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
    return 0;
}

int CRabbitmqClient::Consumer(const string &strQueueName, vector<string> &message_array, int GetNum, struct timeval *timeout) {
    if (NULL == m_pConn) {
        fprintf(stderr, "Consumer m_pConn is null, Consumer failed\n");
        return -1;
    }

    amqp_channel_open(m_pConn, m_iChannel);
    if (0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "open channel")) {
        amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
        return -2;
    }

    amqp_basic_qos(m_pConn, m_iChannel, 0, GetNum, 0);
    int ack = 1; // no_ack    是否需要确认消息后再从队列中删除消息
    amqp_bytes_t queuename= amqp_cstring_bytes(strQueueName.c_str());
    amqp_basic_consume(m_pConn, m_iChannel, queuename, amqp_empty_bytes, 0, ack, 0, amqp_empty_table);

    if (0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "Consuming")) {
        amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
        return -3;
    }

    int hasget = 0;
    amqp_rpc_reply_t res;
    amqp_envelope_t envelope;
    while (GetNum > 0) {
        amqp_maybe_release_buffers(m_pConn);
        res = amqp_consume_message(m_pConn, &envelope, timeout, 0);
        if (AMQP_RESPONSE_NORMAL != res.reply_type) {
            fprintf(stderr, "Consumer amqp_channel_close failed\n");
            amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);

            if (0 == hasget)
                return -res.reply_type;
            else
                return 0;
        }

        string str((char *)envelope.message.body.bytes, (char *)envelope.message.body.bytes + envelope.message.body.len);
        message_array.push_back(str);
        int rtn = amqp_basic_ack(m_pConn, m_iChannel, envelope.delivery_tag, 1);
        amqp_destroy_envelope(&envelope);
        if (rtn != 0) {
            amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
            return -4;
        }

        GetNum--;
        hasget++;
        usleep(1);
    }

    return 0;
}

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

3)main.cpp


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <iostream>

#include "rabbitmqclient.h"


int main()
{
    CRabbitmqClient objRabbitmq;

    std::string strIP = "127.0.0.1";
    int iPort = 5672;
    std::string strUser = "myMQ";
    std::string strPasswd = "myMQ";


    int iRet = objRabbitmq.Connect(strIP, iPort, strUser, strPasswd);
    printf("Rabbitmq Connect Ret: %d\n", iRet);


    std::string strExchange = "ExchangeTest";
    std::string strRoutekey = "routekeyTest";
    std::string strQueuename = "queueTest";

    // 可选操作 Declare Exchange
    iRet = objRabbitmq.ExchangeDeclare(strExchange, "direct");
    printf("Rabbitmq ExchangeDeclare Ret: %d\n", iRet);

    // 可选操作(接收) Declare Queue
    iRet = objRabbitmq.QueueDeclare(strQueuename);
    printf("Rabbitmq QueueDeclare Ret: %d\n", iRet);

    // 可选操作(接收) Queue Bind
    iRet = objRabbitmq.QueueBind(strQueuename, strExchange, strRoutekey);
    printf("Rabbitmq QueueBind Ret: %d\n", iRet);

    // Send Msg
    std::string strSendMsg1 = "rabbitmq send test msg1";
    std::string strSendMsg2 = "rabbitmq send test msg2";
    iRet = objRabbitmq.Publish(strSendMsg1, strExchange, strRoutekey);
    printf("Rabbitmq Publish 1 Ret: %d\n", iRet);
    iRet = objRabbitmq.Publish(strSendMsg2, strExchange, strRoutekey);
    printf("Rabbitmq Publish 2 Ret: %d\n", iRet);

    // Recv Msg
    std::vector<std::string> vecRecvMsg;
    iRet = objRabbitmq.Consumer(strQueuename, vecRecvMsg, 2);
    printf("Rabbitmq Consumer Ret: %d\n", iRet);

    for (size_t i=0; i<vecRecvMsg.size(); ++i) {
        printf("Consumer: %s\n", vecRecvMsg[i].c_str());
    }

    objRabbitmq.Disconnect();
    return 0;
}

转自:https://blog.csdn.net/LT_lover/article/details/80915711#commentBox
注:
1)过程中用到了rabbitmq的静态库需要自己下载代码编译生成
https://github.com/alanxz/SimpleAmqpClient

### 回答1: RabbitMQ是一种开源的消息中间件工具,用于在分布式系统之间进行高效可靠的消息传递。 在RabbitMQ中,发送消息是一个非常简单的过程。首先,我们需要创建一个连接到RabbitMQ的连接;然后,通过该连接创建一个通道来执行消息传递操作。 下一步是声明一个消息队列,消息将被发送到这个队列中,并且接收者将从同一个队列中接收消息。我们可以使用`channel.queueDeclare()`方法来声明队列,并指定队列的名称、是否持久化等参数。 接下来,我们可以使用`channel.basicPublish()`方法来向队列发送消息。该方法需要指定交换机的名称、队列的名称、消息的正文,以及一些其他的属性。 当消息被发送到队列后,它会等待接收者来获取并处理这些消息。使用RabbitMQ提供的消费者模式,我们可以编写一个消费者程序,从队列中获取消息,并执行我们定义的处理逻辑。消费者程序可以使用`channel.basicConsume()`方法来从队列中获取消息,并指定处理消息的逻辑函数。 最后,我们需要关闭RabbitMQ连接和通道。可以使用`channel.close()`和`connection.close()`方法来关闭通道和连接。 通过以上步骤,我们可以简单地使用RabbitMQ发送消息。RabbitMQ提供了强大的可靠性和灵活性,可以在分布式系统中实现高效的消息传递。 ### 回答2: RabbitMQ是一种开源的消息中间件,用于在分布式系统中进行消息传递。它遵循AMQP(高级消息队列协议)标准,同时提供了多种客户端库,可以用于不同编程语言进行消息的发送和接收。 在使用RabbitMQ发送消息时,首先需要创建一个连接,然后创建一个通道。通道是消息传递的通道,每个通道可以用于发送或接收消息。创建通道后,可以使用该通道的方法来发送消息。 首先需要指定消息的目标队列,可以使用队列的名称来指定。如果目标队列不存在,可以使用`channel.queueDeclare()`方法来声明创建队列。在发送消息前,还可以使用`channel.exchangeDeclare()`来声明交换机(Exchange),根据需要进行绑定或者配置交换机的属性。 完成了队列和交换机的声明后,可以使用`channel.basicPublish()`方法来发送消息。该方法需要指定交换机的名称(可选,如果没有指定则使用默认的交换机)、目标队列的名称、消息的属性和消息的内容。方法调用成功后,消息将发送到指定的队列或交换机中。 发送消息后,RabbitMQ会异步地将消息传递给消费者,消费者可以使用订阅该队列的方式来消费消息。消费者可以通过订阅队列的方式来接收消息,也可以通过`channel.basicConsume()`方法来主动拉取消息,或者使用其他高级功能来消费消息。 总结来说,使用RabbitMQ发送消息的流程包括:创建连接和通道、声明队列和交换机、发送消息。通过这个简单的流程,可以实现分布式系统中的消息传递和异步通信。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值