Windows下实现C++ 连接ActiveMQ

1.什么是ActiveMQ?

ActiveMQ是Apache软件基金会所研发的开放源代码消息中间件;由于ActiveMQ是一个纯Java程序,因此只需要操作系统支持Java虚拟机,ActiveMQ便可执行。
支持的编程语言包括:C、C++、C#、Delphi、Erlang、Adobe Flash、Haskell、Java、JavaScript、Perl、PHP、Pike、Python和Ruby。

2.能用来做什么?

通过ActiveMQ能实现消息的网络通讯。生产者生产推动消息到ActiveMQ服务,消费者连接ActiveMQ实现消息的接收。
在这里插入图片描述

3. 支持的消息类型

主要有Queues和Topics两种消息类型。Queues是一对一的模式,一个生产者对应一个消费者,消息被消费了就没有了。 Topics是多对多的模式,多个生产者,多个消费者。

4.本地安装ActiveMQ服务

4.1 下载地址

http://activemq.apache.org/
有经典版和高性能版。我使用的是经典版

4.2 启动

下载好后,解压,双击bin下的win64下的activemq.bat启动服务。
在这里插入图片描述
可用浏览器登录ActiveMQ的管理端,可以查看消息和连接等情况。如有账号和密码都是admin吧。
http://127.0.0.1:8161/admin

4.3 配置文件activemq.xml

修改配置文件,实现消息的恢复,当消费者客户端重启后能恢复历史消息。
在这里插入图片描述

5.C++实现连接ActiveMQ

ActiveMQ服务起来后,现在就是实现消息的生产者和消费者了。

5.1 下载相关接口

下载activemq-cpp对应库代码并编译:
http://www.apache.org/dyn/closer.lua/activemq/activemq-cpp/
下载环境工具库,否则activemq-cpp编译不过的:
http://apr.apache.org/download.cgi
在这里插入图片描述
网上别的人说要好几个环境库,我就只用了apr。

5.2 编译

本人使用的是vs2019编译,它原来工程默认的是2010,需要升级下工程属性中的,常规,平台工具集,到v142。

5.2.1 编译activemq-cpp工程

在这里插入图片描述
如报错找不到头文件apr_pools.h的话,需要把apr库中的头文件文件夹include包含到工程中。
在这里插入图片描述
修改工程属性后应该就能编译过了:
在这里插入图片描述

5.2.2 编译libapr工程生成libapr-1.lib和libapr-1.dll库

在这里插入图片描述
可能会报错一大推编译错误错误,参考这篇文章,https://blog.csdn.net/tiger_xs/article/details/100038183,需要在include文件夹下找到apr.hw文件,找到宏定义“#define _WIN32_WINNT 0x0501”,将0x0501改为0x0600。

5.2.3 编译activemq-cpp.example例子工程,运行例子

找不到头文件的加包含目录,找不到libapr-1.lib库的,把这个库复制到这里:
在这里插入图片描述
然后,在ActiveMQ服务启动了的情况下,这个例子就能启动啦。

这个工程的main.cpp给了生产者和消费者的例子代码,它是起了两个线程程。可以通过这个例子根据自己的需要修改成自己的工程。

6.实际项目中的改造

下面是我通过改动实现消费者的单例模式,这样就可以在项目中各个地方调用,实现消息的传输。
为了防止阻塞,实际情况发消息的时候是转了线程的。这里注释掉了。

ActiveMQ.h

#include <activemq/library/ActiveMQCPP.h>
#include <decaf/lang/Thread.h>
#include <decaf/lang/Runnable.h>
#include <decaf/util/concurrent/CountDownLatch.h>
#include <decaf/lang/Integer.h>
#include <decaf/lang/Long.h>
#include <decaf/lang/System.h>
#include <activemq/core/ActiveMQConnectionFactory.h>
#include <activemq/util/Config.h>
#include <cms/Connection.h>
#include <cms/Session.h>
#include <cms/TextMessage.h>
#include <cms/BytesMessage.h>
#include <cms/MapMessage.h>
#include <cms/ExceptionListener.h>
#include <cms/MessageListener.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <memory>
#include<boost/asio.hpp>
#include<boost/thread.hpp>

using namespace decaf::lang;
using namespace cms;
using namespace decaf::util::concurrent;
class MQProducer //: public Runnable
{
public:
    static void init();
    static MQProducer* instance();
    int sendMessage(const std::string& msg);
private:
    MQProducer(const std::string& brokerURI, bool useTopic = false, bool sessionTransacted = false);
    virtual ~MQProducer();
    void close();
    virtual void run();
    MQProducer(const MQProducer&);
    MQProducer& operator=(const MQProducer&);
    void cleanup();
    void doSendMessage(const string& msg);
    void getHostIP();
    
private:
    Connection* m_pConnection;
    Session* m_pSession;
    Destination* m_pDestination;
    MessageProducer* m_pProducer;
    bool m_bUseTopic;
    bool m_bSessionTransacted;
    std::string m_brokerURI;
    boost::asio::io_service m_ioservice;
    boost::asio::io_service::work m_work;
    std::string m_server;
    static MQProducer* s_pMQProducer;
};

ActiveMQ.cpp

#include <Utils/ActiveMQ.h>

using namespace activemq::core;
using namespace decaf::util;

MQProducer* MQProducer::s_pMQProducer = NULL; 

MQProducer* MQProducer::instance()
{
    return s_pMQProducer;
}

//有点特殊的单子,确保多线程前,调用了init。
void MQProducer::init()
{
    if (s_pMQProducer == NULL)
    {
        string serverip = "127.0.0.1:16161";
         std::string brokerURI =
            "failover:(tcp://"+ serverip+
            "?wireFormat=openwire"
            //        "&transport.useInactivityMonitor=false"
            //        "&connection.alwaysSyncSend=true"
            "&connection.useAsyncSend=true"
            //        "?transport.commandTracingEnabled=true"
            //        "&transport.tcpTracingEnabled=true"
            //        "&wireFormat.tightEncodingEnabled=true"
            ")";
        s_pMQProducer = new MQProducer(brokerURI, true, false);
    }
}

MQProducer::MQProducer(const std::string& brokerURI, bool useTopic, bool sessionTransacted )
    : m_pConnection(NULL)
    , m_pSession(NULL)
    , m_pDestination(NULL)
    , m_pProducer(NULL)
    , m_bUseTopic(useTopic)
    , m_bSessionTransacted(sessionTransacted)
    , m_brokerURI(brokerURI)
    , m_work(m_ioservice)
    , m_server("")
    {
        activemq::library::ActiveMQCPP::initializeLibrary();
        this->run();
    }

MQProducer::~MQProducer() 
{
    cleanup();
    activemq::library::ActiveMQCPP::shutdownLibrary();
}

void MQProducer::close() 
{
    this->cleanup();
}

void MQProducer::run() 
{
    try 
    {
        // Create a ConnectionFactory
        auto_ptr<ConnectionFactory> connectionFactory(ConnectionFactory::createCMSConnectionFactory(m_brokerURI));
        //ActiveMQConnectionFactory* connectionFactory = new ActiveMQConnectionFactory(m_brokerURI);

        // Create a Connection
        //connectionFactory->setConnectResponseTimeout(30000);
        m_pConnection = connectionFactory->createConnection();
        m_pConnection->start();

        // Create a Session
        if (this->m_bSessionTransacted) 
        {
            m_pSession = m_pConnection->createSession(Session::SESSION_TRANSACTED);
        }
        else 
        {
            m_pSession = m_pConnection->createSession(Session::AUTO_ACKNOWLEDGE);
        }

        // Create the destination (Topic or Queue)
        if (m_bUseTopic)
        {
            m_pDestination = m_pSession->createTopic("alert");
        }
        else 
        {
            m_pDestination = m_pSession->createQueue("alert");
        }

        // Create a MessageProducer from the Session to the Topic or Queue
        m_pProducer = m_pSession->createProducer(m_pDestination);
        m_pProducer->setDeliveryMode(DeliveryMode::NON_PERSISTENT);
    }
    catch (CMSException& e) 
    {
        e.printStackTrace();
    }
}

int MQProducer::sendMessage(const string& msg)
{
    //m_ioservice.post(boost::bind(&utils::MQProducer::doSendMessage, this, msg));
    doSendMessage(msg);
    return 0;
}

void MQProducer::doSendMessage(const string& msg)
{
    try
    {
       //生产者怎么封装休息,消费者那里就要怎么解析消息,这里用的是MapMessage字典方式的消息
        std::auto_ptr<MapMessage> message(m_pSession->createMapMessage());
        message->setString("Instance", "来自BJ");
        message->setString("Severity", "ERROR");
        string text(msg);
        text = boost::locale::conv::between(text, "UTF-8", "GBK");
        message->setString("Message", text);
        m_pProducer->send(message.get());
    }
    catch (CMSException& e)
    {
        e.printStackTrace();
    }
}

void MQProducer::cleanup()
{
    if (m_pConnection != NULL) 
    {
        try 
        {
            m_pConnection->close();
        }
        catch (cms::CMSException& ex) 
        {
            ex.printStackTrace();
        }
    }

    // Destroy resources.
    try {
        delete m_pDestination;
        m_pDestination = NULL;
        delete m_pProducer;
        m_pProducer = NULL;
        delete m_pSession;
        m_pSession = NULL;
        delete m_pConnection;
        m_pConnection = NULL;
    }
    catch (CMSException& e) 
    {
        e.printStackTrace();
    }
}

大概这样,未必能编译过。不过也应该差不多了。
main.cpp

#include <ActiveMQ.h>
int main(int argc, char** argv)
{
    MQProducer::init();
    !MQProducer::instance() ? 0 : utils::MQProducer::instance()->sendMessage("test");
}

7.下载地址,头文件和vs2019编译的库

链接:https://pan.baidu.com/s/1gbxPPgLh5i6u87bKMv81kw
提取码:0ang

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
要使用ActiveMQ-CPP库实现上传数据功能,你需要按照以下步骤进行操作: 1. 首先,确保你已经安装了ActiveMQ-CPP库。你可以在ActiveMQ官方网站上找到相应的下载链接和安装说明。 2. 在你的C++项目中,包含ActiveMQ-CPP的头文件: ```cpp #include <activemq/core/ActiveMQConnectionFactory.h> #include <activemq/library/ActiveMQCPP.h> ``` 3. 创建一个连接工厂,并设置ActiveMQ服务器的连接地址和端口: ```cpp std::string brokerURI = "tcp://localhost:61616"; activemq::core::ActiveMQConnectionFactory connectionFactory(brokerURI); ``` 4. 创建一个连接,并启动它: ```cpp activemq::core::Connection* connection = connectionFactory.createConnection(); connection->start(); ``` 5. 创建一个会话,并指定会话类型和订阅目的地: ```cpp activemq::core::Session* session = connection->createSession(activemq::core::Session::AUTO_ACKNOWLEDGE); activemq::core::Destination* destination = session->createQueue("your_queue_name"); ``` 6. 创建一个消息生产者,用于发送数据: ```cpp activemq::core::MessageProducer* producer = session->createProducer(destination); ``` 7. 构建一个消息对象,并设置消息内容: ```cpp activemq::core::TextMessage* message = session->createTextMessage(); message->setText("Your data here"); ``` 8. 发送消息到目的地: ```cpp producer->send(message); ``` 9. 清理资源并关闭连接: ```cpp delete message; delete producer; session->close(); connection->close(); ``` 这只是一个基本的示例,你可以根据你的需求进行进一步的代码编写和功能实现。请确保在使用完资源后正确释放它们,以避免内存泄漏。 希望这个示例能帮到你,如果你还有其他问题,请随时提问!
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值