Active MQ C++实现通讯
Kagula
2011-9-13
简介
在参考资料[2]的基础上介绍如何用C++调用Active MQ的客户端API。
环境:[1]Windows XP SP3
[2]Visual Studio 2008 SP1
阅读前提:[1]熟悉Microsoft Visual Studio下的C++编程
[2]熟悉《Active MQ使用》这篇文章中的内容,即参考资料[2]
正文
CMS (stands for C++ Messaging Service)类似于JMS API用于同Message Brokers通讯(例如Active MQ)。
Active MQ-CPP是客户端库。通过参考资料[3]下载“Active MQ-CPP v3.4.0 (activemq-cpp-library-3.4.0-src.zip)”
准备开发环境
APR(Apache portable Run-time libraries,Apache可移植运行库)的目的如其名称一样,主要为上层的应用程序提供一个可以跨越多操作系统平台使用的底层支持接口库。
你必须从参考[4]中下载apr-iconv包、apr-util包、apr包等三个包,并解压缩到
C:\work\apr\
C:\work\apr-iconv\
C:\work\apr-util\
等以上三个目录(必须是在上面的路径中,否则VS2008中会找不到工程依赖文件和依赖函数实现)
第一步:apr-iconv包的配置
下载http://apache.osuosl.org/apr/apr-iconv-1.2.1-win32-src-r2.zip
解压后打开包内的apriconv.dsp文件编译出Release版本的apriconv-1.lib文件。
配置VS2008的头文件搜索路径为
C:\work\apr-iconv\include
配置VS2008的库文件搜索路径为
C:\work\apr-iconv\\LibR
第二步:apr-util包的配置
参考资料[4]下载apr-util-1.3.12-win32-src.zip 包中的源码,编译aprutil工作空间中的aprutil项目,生成aprutil-1.lib、libaprutil-1.lib。
把“c:\work\apr-util\include”目录配置到VS2008头文件搜索路径里
把“c:\work\apr-util\LibR”目录配置到VS2008库文件搜索路径里
把“c:\work\apr-util\release”目录配置到VS2008库文件搜索路径里
第三步:apr基本包的配置
参考资料[4]下载、编译apr-1.4.5-win32-src.zip 包中的源码。
编译好后在LibR目录里生成apr-1.lib库、libapr-1.lib。否则activemq-cpp的acitvemq-cpp-example项目编译时会找不到库文件。
把“c:\work\apr\include”目录配置到VS2008头文件搜索路径里
把“c:\work\apr\LibR”目录配置到VS2008库文件搜索路径里
把“C:\work\apr\Release”目录配置到VS2008库文件搜索路径里
第四步:CppUnit包的配置
在下面网址下载
http://sourceforge.net/projects/cppunit/files/cppunit/1.12.1/cppunit-1.12.1.tar.gz/download
解压缩cppunit-1.12.1.tar.gz包,并以Release方式编译
把“D:\cppunit-1.12.1\include” 目录配置到VS2008头文件搜索路径里
把“D:\cppunit-1.12.1\lib”目录配置到VS2008库文件搜索路径里
其中上面的D:\是我的解压路径,你也可以是其它路径。
第五步:activemq-cpp-library-3.4.0包的配置
解包activemq-cpp-library-3.3.0-src.zip文件(从参考资料[3]中下载),并以Release方式编译,如果前面几步正确,这一步不会产生任何错误。
这个zip包里,含activemq-cpp-example项目,里面有个C++源码示例,我这里的源码片段就是参考那里的。
把“D:\activemq-cpp-library-3.4.0\src\main” 目录配置到VS2008头文件搜索路径里
把“D:\activemq-cpp-library-3.4.0\src\main\decaf\internal” 目录配置到VS2008头文件搜索路径里
把“D:\activemq-cpp-library-3.4.0\vs2008-build\Win32\Release”目录配置到VS2008库文件搜索路径里
其中上面的D:\是我的解压路径,你也可以是其它路径。
使用“activemq-cpp”提供的API只要配置其头文件存放路径就可以了。
C++样例
要运行样例文件,请确保以releaseDLL和debugDLL方式编译成功以上各个依赖包。以Debug方式调试你的应用程序时必须使用activemq-cppd.lib库文件及其对应的activemq-cppd.dll动态链接库文件,否则创建connectionFactory对象会出错。
依赖库列表(含路径,四个动态链接库,三个静态库,不包括ws2_32.lib)
D:\activemq-cpp-library-3.4.0\vs2008-build\Win32\DebugDLL\activemq-cppd.lib
D:\activemq-cpp-library-3.4.0\vs2008-build\Win32\DebugDLL\activemq-cppd.dll
C:\work\apr\Release\libapr-1.lib
C:\work\apr\Release\libapr-1.dll
C:\work\apr-util\Release \libaprutil-1.dll
C:\work\apr-util\Release \libaprutil-1.lib
C:\work\apr-iconv\Release\ libapriconv-1.dll
新建Win32 Console项目在VS2008里,修改[Configuration Properties]->[Linker]->[Input]->[Additional Dependencies]属性为
ws2_32.lib activemq-cppd.lib libapr-1.lib libaprutil-1.lib
把需要的动态链接库文件复制到当前项目的运行目录中。
以Debug方式运行成功后,http://127.0.0.1:8161/admin/queues.jsp
你会发现多个了“FromMyCPlusPlus”队列,里面已经存放了刚才发送的消息。
下面是我的完整源码testActiveMQ.cpp文件
- // testActiveMQ.cpp : Defines the entry point for the console application.
- //
- #include "stdafx.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>
- using namespace activemq::core;
- using namespace decaf::util::concurrent;
- using namespace decaf::util;
- using namespace decaf::lang;
- using namespace cms;
- using namespace std;
- int _tmain(int argc, _TCHAR* argv[])
- {
- activemq::library::ActiveMQCPP::initializeLibrary();
- Connection* connection;
- Session* session;
- Destination* destination;
- MessageProducer* producer;
- std::string brokerURI("failover:(tcp://localhost:61616)");
- try {
- // Create a ConnectionFactory
- auto_ptr<ConnectionFactory> connectionFactory( ConnectionFactory::createCMSConnectionFactory( brokerURI ) );
- // Create a Connection
- connection = connectionFactory->createConnection();
- connection->start();
- // Create a Session
- session = connection->createSession( Session::AUTO_ACKNOWLEDGE );
- // Create the destination (Topic or Queue)
- destination = session->createQueue( "FromMyCPlusPlus" );
- // Create a MessageProducer from the Session to the Topic or Queue
- producer = session->createProducer( destination );
- producer->setDeliveryMode( DeliveryMode::NON_PERSISTENT );
- // Create a messages
- string text("Hello world from c++");
- for( int ix=0; ix<3; ++ix ){
- TextMessage* message = session->createTextMessage( text );
- message->setIntProperty( "Integer", ix );
- producer->send( message );
- delete message;
- }
- }catch ( CMSException& e ) {
- e.printStackTrace();
- }
- //释放资源
- try{
- if( destination != NULL ) delete destination;
- }catch ( CMSException& e ) { e.printStackTrace(); }
- destination = NULL;
- try{
- if( producer != NULL ) delete producer;
- }catch ( CMSException& e ) { e.printStackTrace(); }
- producer = NULL;
- // Close open resources.
- try{
- if( session != NULL ) session->close();
- if( connection != NULL ) connection->close();
- }catch ( CMSException& e ) { e.printStackTrace(); }
- try{
- if( session != NULL ) delete session;
- }catch ( CMSException& e ) { e.printStackTrace(); }
- session = NULL;
- try{
- if( connection != NULL ) delete connection;
- }catch ( CMSException& e ) { e.printStackTrace(); }
- connection = NULL;
- activemq::library::ActiveMQCPP::shutdownLibrary();
- return 0;
- }
// testActiveMQ.cpp : Defines the entry point for the console application.
//
#include "stdafx.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>
using namespace activemq::core;
using namespace decaf::util::concurrent;
using namespace decaf::util;
using namespace decaf::lang;
using namespace cms;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
activemq::library::ActiveMQCPP::initializeLibrary();
Connection* connection;
Session* session;
Destination* destination;
MessageProducer* producer;
std::string brokerURI("failover:(tcp://localhost:61616)");
try {
// Create a ConnectionFactory
auto_ptr<ConnectionFactory> connectionFactory( ConnectionFactory::createCMSConnectionFactory( brokerURI ) );
// Create a Connection
connection = connectionFactory->createConnection();
connection->start();
// Create a Session
session = connection->createSession( Session::AUTO_ACKNOWLEDGE );
// Create the destination (Topic or Queue)
destination = session->createQueue( "FromMyCPlusPlus" );
// Create a MessageProducer from the Session to the Topic or Queue
producer = session->createProducer( destination );
producer->setDeliveryMode( DeliveryMode::NON_PERSISTENT );
// Create a messages
string text("Hello world from c++");
for( int ix=0; ix<3; ++ix ){
TextMessage* message = session->createTextMessage( text );
message->setIntProperty( "Integer", ix );
producer->send( message );
delete message;
}
}catch ( CMSException& e ) {
e.printStackTrace();
}
//释放资源
try{
if( destination != NULL ) delete destination;
}catch ( CMSException& e ) { e.printStackTrace(); }
destination = NULL;
try{
if( producer != NULL ) delete producer;
}catch ( CMSException& e ) { e.printStackTrace(); }
producer = NULL;
// Close open resources.
try{
if( session != NULL ) session->close();
if( connection != NULL ) connection->close();
}catch ( CMSException& e ) { e.printStackTrace(); }
try{
if( session != NULL ) delete session;
}catch ( CMSException& e ) { e.printStackTrace(); }
session = NULL;
try{
if( connection != NULL ) delete connection;
}catch ( CMSException& e ) { e.printStackTrace(); }
connection = NULL;
activemq::library::ActiveMQCPP::shutdownLibrary();
return 0;
}
参考资料
[1]《解决Active MQ中,Java与C++交互中文乱码问题》
http://www.blogjava.net/javagrass/archive/2011/05/06/349660.html
[2]《Active MQ使用》
http://blog.csdn.net/lee353086/article/details/6753858
[3]《Active MQ CMS》
http://activemq.apache.org/cms/
[4]Apache Portable Runtime Project