很早前就仓促的接触过activemq,但当时太赶时间.后面发现activemq 需要了解的东西实在是太多了.

关于activemq 一直想起一遍文章.但也一直缺少自己的见解.或许是网上这些文章太多了.也可能是自己知识还不足够.

0,activemq-cpp 能解决什么问题.

实际应用就是让开发者能从多线程,多消息通信中解救出来.更多的关注应用逻辑.

CMS (stands for C++ Messaging Service) is a JMS-like API for C++ for interfacing with Message Brokers such as Apache ActiveMQ. CMS helps to make your C++ client code much neater and easier to follow. To get a better feel for CMS try the API Reference. ActiveMQ-CPP is a client only library, a message broker such as Apache ActiveMQ is still needed for your clients to communicate.

Our implementation of CMS is called ActiveMQ-CPP, which has an architecture that allows for pluggable transports and wire formats. Currently we support the OpenWire and Stomp protocols, both over TCP and SSL, we also now support a Failover Transport for more reliable client operation. In addition to CMS, ActiveMQ-CPP also provides a robust set of classes that support platform independent constructs such as threading, I/O, sockets, etc. You may find many of these utilities very useful, such as a Java like Thread class or the "synchronized" macro that let's you use a Java-like synchronization on any object that implements the activemq::concurrent::Synchronizable interface. ActiveMQ-CPP is released under the Apache 2.0 License

大意:

CMS (C++ 消息 服务)是一个面象apache activemq 的 消息 中间层的C++接口.

CMS的实现 叫做activemq-cpp ,不过当前只支持 openwire,amqp,TCP,ssl. 现在还支持 主备切换功能(这个是重点,当时我不懂,结果就走了弯路!_!).

-_- ,意思是 activemq\conf\activemq.xml中的stomp,mqtt,ws 是没办法的.

  1. <transportConnectors>
  2. <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
  3. <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  4. <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  5. <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  6. <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  7. <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  8. </transportConnectors>

1,acticvemq-cpp 的配置使用.

参考:Active MQ  C++实现通讯 http://blog.csdn.net/lee353086/article/details/6777261

activemq-cpp下载地址:

http://activemq.apache.org/cms/download.html

相关依赖库

在 http://activemq.apache.org/cms/building.html 中是有介绍的.不过是en的.

还是再说下吧.本人en也特差.

"With versions of ActiveMQ-CPP 2.2 and later, we have a dependency on the Apache Portable Runtime project. You'll need to install APR on your system before you'll be able to build ActiveMQ-CPP."

"The package contains a complete set of CppUnit tests. In order for you to build an run the tests, you will need to download and install the CppUnit library. See http://cppunit.sourceforge.net/cppunit-wiki"

所以就包含了:apr,apr-iconv,apr-util,cppunit.

http://mirrors.hust.edu.cn/apache/apr/

中可以下载 apr,apr-iconv,apr-util(版本号都找最高的,不要一高一低,不然编译会出问题).

apr-1.5.1-win32-src.zip,

apr-iconv-1.2.1-win32-src-r2.zip,

apr-util-1.5.4-win32-src.zip.

解压后记得重命令文件夹,去掉版本号,改成如下图,不然工程编译时默认的 [附加包含目录] 是找不到的.

所有文件夹放在一个根目录下.

打开  activemq-cpp-library\vs2008-build\activemq-cpp.sln

依次添加[现在项目]:libapr.vcproj,libapriconv.vcproj,libaprutil.vcproj. 只需要lib项就行了.

最后项目图:

libapriconv.vcproj,libaprutil.vcproj 的[项目依赖项]都需要libapr

activemq-cpp 的[项目依赖项]需要libapriconv,libaprutil,libapr.

activemq-cpp 的[附加包含目录] 需要包含 这三个的的include目录.

经过漫长的编译后,

这个大lib文件就出来.

activemq-cpp-example 这个工程 ,就有 hello world 的代码.

2,activemq-cpp-example 项目代码解析.

通过这个项目可以让我们更好的认识 activemq-cpp的结构.

  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17.  
  18. // START SNIPPET: demo
  19.  
  20. #include <activemq/library/ActiveMQCPP.h>
  21. #include <decaf/lang/Thread.h>
  22. #include <decaf/lang/Runnable.h>
  23. #include <decaf/util/concurrent/CountDownLatch.h>
  24. #include <decaf/lang/Integer.h>
  25. #include <decaf/lang/Long.h>
  26. #include <decaf/lang/System.h>
  27. #include <activemq/core/ActiveMQConnectionFactory.h>
  28. #include <activemq/util/Config.h>
  29. #include <cms/Connection.h>
  30. #include <cms/Session.h>
  31. #include <cms/TextMessage.h>
  32. #include <cms/BytesMessage.h>
  33. #include <cms/MapMessage.h>
  34. #include <cms/ExceptionListener.h>
  35. #include <cms/MessageListener.h>
  36. #include <stdlib.h>
  37. #include <stdio.h>
  38. #include <iostream>
  39. #include <memory>
  40.  
  41. using namespace activemq::core;
  42. using namespace decaf::util::concurrent;
  43. using namespace decaf::util;
  44. using namespace decaf::lang;
  45. using namespace cms;
  46. using namespace std;
  47.  
  48. class HelloWorldProducer : public Runnable {
  49. private:
  50.  
  51. Connection* connection;
  52. Session* session;
  53. Destination* destination;
  54. MessageProducer* producer;
  55. int numMessages;
  56. bool useTopic;
  57. bool sessionTransacted;
  58. std::string brokerURI;
  59.  
  60. private:
  61.  
  62. HelloWorldProducer(const HelloWorldProducer&);
  63. HelloWorldProducer& operator=(const HelloWorldProducer&);
  64.  
  65. public:
  66.  
  67. HelloWorldProducer(const std::string& brokerURI, int numMessages, bool useTopic = false, bool sessionTransacted = false) :
  68. connection(NULL),
  69. session(NULL),
  70. destination(NULL),
  71. producer(NULL),
  72. numMessages(numMessages),
  73. useTopic(useTopic),
  74. sessionTransacted(sessionTransacted),
  75. brokerURI(brokerURI) {
  76. }
  77.  
  78. virtual ~HelloWorldProducer(){
  79. cleanup();
  80. }
  81.  
  82. void close() {
  83. this->cleanup();
  84. }
  85.  
  86. virtual void run() {
  87.  
  88. try {
  89.  
  90. // Create a ConnectionFactory
  91. auto_ptr<ConnectionFactory> connectionFactory(
  92. ConnectionFactory::createCMSConnectionFactory(brokerURI));
  93.  
  94. // Create a Connection
  95. connection = connectionFactory->createConnection();
  96. connection->start();
  97.  
  98. // Create a Session
  99. if (this->sessionTransacted) {
  100. session = connection->createSession(Session::SESSION_TRANSACTED);
  101. } else {
  102. session = connection->createSession(Session::AUTO_ACKNOWLEDGE);
  103. }
  104.  
  105. // Create the destination (Topic or Queue)
  106. if (useTopic) {
  107. destination = session->createTopic("TEST.FOO");
  108. } else {
  109. destination = session->createQueue("TEST.FOO");
  110. }
  111.  
  112. // Create a MessageProducer from the Session to the Topic or Queue
  113. producer = session->createProducer(destination);
  114. producer->setDeliveryMode(DeliveryMode::NON_PERSISTENT);
  115.  
  116. // Create the Thread Id String
  117. string threadIdStr = Long::toString(Thread::currentThread()->getId());
  118.  
  119. // Create a messages
  120. string text = (string) "Hello world! from thread " + threadIdStr;
  121.  
  122. for (int ix = ; ix < numMessages; ++ix) {
  123. std::auto_ptr<TextMessage> message(session->createTextMessage(text));
  124. message->setIntProperty("Integer", ix);
  125. printf("Sent message #%d from thread %s\n", ix + , threadIdStr.c_str());
  126. producer->send(message.get());
  127. }
  128.  
  129. } catch (CMSException& e) {
  130. e.printStackTrace();
  131. }
  132. }
  133.  
  134. private:
  135.  
  136. void cleanup() {
  137.  
  138. if (connection != NULL) {
  139. try {
  140. connection->close();
  141. } catch (cms::CMSException& ex) {
  142. ex.printStackTrace();
  143. }
  144. }
  145.  
  146. // Destroy resources.
  147. try {
  148. delete destination;
  149. destination = NULL;
  150. delete producer;
  151. producer = NULL;
  152. delete session;
  153. session = NULL;
  154. delete connection;
  155. connection = NULL;
  156. } catch (CMSException& e) {
  157. e.printStackTrace();
  158. }
  159. }
  160. };
  161.  
  162. class HelloWorldConsumer : public ExceptionListener,
  163. public MessageListener,
  164. public Runnable {
  165.  
  166. private:
  167.  
  168. CountDownLatch latch;
  169. CountDownLatch doneLatch;
  170. Connection* connection;
  171. Session* session;
  172. Destination* destination;
  173. MessageConsumer* consumer;
  174. long waitMillis;
  175. bool useTopic;
  176. bool sessionTransacted;
  177. std::string brokerURI;
  178.  
  179. private:
  180.  
  181. HelloWorldConsumer(const HelloWorldConsumer&);
  182. HelloWorldConsumer& operator=(const HelloWorldConsumer&);
  183.  
  184. public:
  185.  
  186. HelloWorldConsumer(const std::string& brokerURI, int numMessages, bool useTopic = false, bool sessionTransacted = false, int waitMillis = ) :
  187. latch(),
  188. doneLatch(numMessages),
  189. connection(NULL),
  190. session(NULL),
  191. destination(NULL),
  192. consumer(NULL),
  193. waitMillis(waitMillis),
  194. useTopic(useTopic),
  195. sessionTransacted(sessionTransacted),
  196. brokerURI(brokerURI) {
  197. }
  198.  
  199. virtual ~HelloWorldConsumer() {
  200. cleanup();
  201. }
  202.  
  203. void close() {
  204. this->cleanup();
  205. }
  206.  
  207. void waitUntilReady() {
  208. latch.await();
  209. }
  210.  
  211. virtual void run() {
  212.  
  213. try {
  214.  
  215. // Create a ConnectionFactory
  216. auto_ptr<ConnectionFactory> connectionFactory(
  217. ConnectionFactory::createCMSConnectionFactory(brokerURI));
  218.  
  219. // Create a Connection
  220. connection = connectionFactory->createConnection();
  221. connection->start();
  222. connection->setExceptionListener(this);
  223.  
  224. // Create a Session
  225. if (this->sessionTransacted == true) {
  226. session = connection->createSession(Session::SESSION_TRANSACTED);
  227. } else {
  228. session = connection->createSession(Session::AUTO_ACKNOWLEDGE);
  229. }
  230.  
  231. // Create the destination (Topic or Queue)
  232. if (useTopic) {
  233. destination = session->createTopic("TEST.FOO");
  234. } else {
  235. destination = session->createQueue("TEST.FOO");
  236. }
  237.  
  238. // Create a MessageConsumer from the Session to the Topic or Queue
  239. consumer = session->createConsumer(destination);
  240.  
  241. consumer->setMessageListener(this);
  242.  
  243. std::cout.flush();
  244. std::cerr.flush();
  245.  
  246. // Indicate we are ready for messages.
  247. latch.countDown();
  248.  
  249. // Wait while asynchronous messages come in.
  250. doneLatch.await(waitMillis);
  251.  
  252. } catch (CMSException& e) {
  253. // Indicate we are ready for messages.
  254. latch.countDown();
  255. e.printStackTrace();
  256. }
  257. }
  258.  
  259. // Called from the consumer since this class is a registered MessageListener.
  260. virtual void onMessage(const Message* message) {
  261.  
  262. static int count = ;
  263.  
  264. try {
  265. count++;
  266. const TextMessage* textMessage = dynamic_cast<const TextMessage*> (message);
  267. string text = "";
  268.  
  269. if (textMessage != NULL) {
  270. text = textMessage->getText();
  271. } else {
  272. text = "NOT A TEXTMESSAGE!";
  273. }
  274.  
  275. printf("Message #%d Received: %s\n", count, text.c_str());
  276.  
  277. } catch (CMSException& e) {
  278. e.printStackTrace();
  279. }
  280.  
  281. // Commit all messages.
  282. if (this->sessionTransacted) {
  283. session->commit();
  284. }
  285.  
  286. // No matter what, tag the count down latch until done.
  287. doneLatch.countDown();
  288. }
  289.  
  290. // If something bad happens you see it here as this class is also been
  291. // registered as an ExceptionListener with the connection.
  292. virtual void onException(const CMSException& ex AMQCPP_UNUSED) {
  293. printf("CMS Exception occurred. Shutting down client.\n");
  294. ex.printStackTrace();
  295. exit();
  296. }
  297.  
  298. private:
  299.  
  300. void cleanup() {
  301. if (connection != NULL) {
  302. try {
  303. connection->close();
  304. } catch (cms::CMSException& ex) {
  305. ex.printStackTrace();
  306. }
  307. }
  308.  
  309. // Destroy resources.
  310. try {
  311. delete destination;
  312. destination = NULL;
  313. delete consumer;
  314. consumer = NULL;
  315. delete session;
  316. session = NULL;
  317. delete connection;
  318. connection = NULL;
  319. } catch (CMSException& e) {
  320. e.printStackTrace();
  321. }
  322. }
  323. };
  324.  
  325. int main(int argc AMQCPP_UNUSED, char* argv[] AMQCPP_UNUSED) {
  326.  
  327. activemq::library::ActiveMQCPP::initializeLibrary();
  328. {
  329. std::cout << "=====================================================\n";
  330. std::cout << "Starting the example:" << std::endl;
  331. std::cout << "-----------------------------------------------------\n";
  332.  
  333. // Set the URI to point to the IP Address of your broker.
  334. // add any optional params to the url to enable things like
  335. // tightMarshalling or tcp logging etc. See the CMS web site for
  336. // a full list of configuration options.
  337. //
  338. // http://activemq.apache.org/cms/
  339. //
  340. // Wire Format Options:
  341. // =========================
  342. // Use either stomp or openwire, the default ports are different for each
  343. //
  344. // Examples:
  345. // tcp://127.0.0.1:61616 default to openwire
  346. // tcp://127.0.0.1:61616?wireFormat=openwire same as above
  347. // tcp://127.0.0.1:61613?wireFormat=stomp use stomp instead
  348. //
  349. // SSL:
  350. // =========================
  351. // To use SSL you need to specify the location of the trusted Root CA or the
  352. // certificate for the broker you want to connect to. Using the Root CA allows
  353. // you to use failover with multiple servers all using certificates signed by
  354. // the trusted root. If using client authentication you also need to specify
  355. // the location of the client Certificate.
  356. //
  357. // System::setProperty( "decaf.net.ssl.keyStore", "<path>/client.pem" );
  358. // System::setProperty( "decaf.net.ssl.keyStorePassword", "password" );
  359. // System::setProperty( "decaf.net.ssl.trustStore", "<path>/rootCA.pem" );
  360. //
  361. // The you just specify the ssl transport in the URI, for example:
  362. //
  363. // ssl://localhost:61617
  364. //
  365. std::string brokerURI =
  366. "failover:(tcp://localhost:61616"
  367. // "?wireFormat=openwire"
  368. // "&transport.useInactivityMonitor=false"
  369. // "&connection.alwaysSyncSend=true"
  370. // "&connection.useAsyncSend=true"
  371. // "?transport.commandTracingEnabled=true"
  372. // "&transport.tcpTracingEnabled=true"
  373. // "&wireFormat.tightEncodingEnabled=true"
  374. ")";
  375.  
  376. //============================================================
  377. // set to true to use topics instead of queues
  378. // Note in the code above that this causes createTopic or
  379. // createQueue to be used in both consumer an producer.
  380. //============================================================
  381. bool useTopics = true;
  382. bool sessionTransacted = false;
  383. int numMessages = ;
  384.  
  385. long long startTime = System::currentTimeMillis();
  386.  
  387. HelloWorldProducer producer(brokerURI, numMessages, useTopics);
  388. HelloWorldConsumer consumer(brokerURI, numMessages, useTopics, sessionTransacted);
  389.  
  390. // Start the consumer thread.
  391. Thread consumerThread(&consumer);
  392. consumerThread.start();
  393.  
  394. // Wait for the consumer to indicate that its ready to go.
  395. consumer.waitUntilReady();
  396.  
  397. // Start the producer thread.
  398. Thread producerThread(&producer);
  399. producerThread.start();
  400.  
  401. // Wait for the threads to complete.
  402. producerThread.join();
  403. consumerThread.join();
  404.  
  405. long long endTime = System::currentTimeMillis();
  406. double totalTime = (double)(endTime - startTime) / 1000.0;
  407.  
  408. consumer.close();
  409. producer.close();
  410.  
  411. std::cout << "Time to completion = " << totalTime << " seconds." << std::endl;
  412. std::cout << "-----------------------------------------------------\n";
  413. std::cout << "Finished with the example." << std::endl;
  414. std::cout << "=====================================================\n";
  415.  
  416. }
  417. activemq::library::ActiveMQCPP::shutdownLibrary();
  418. }
  419.  
  420. // END SNIPPET: demo

从main()开始吧.

这样便简快速的实现了应用逻辑.

3,activemq的几种通信模式.

可以参考:

http://shmilyaw-hotmail-com.iteye.com/blog/1897635

目前本人需要的是activemq-cpp的 request-response 模式.

4,activemq-cpp的 request-response 模式的应用.

服务器与客户端通信 数据的交互 和 确认.

以下是本人修改后的简单代码,bug可能存在,请指出.

复制两份,一份定义 USE_COMSUMER 一份定义 USE_PRODUCER 就可以生成.

  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17.  
  18. // START SNIPPET: demo
  19.  
  20. #include <activemq/library/ActiveMQCPP.h>
  21. #include <decaf/lang/Thread.h>
  22. #include <decaf/lang/Runnable.h>
  23. #include <decaf/util/concurrent/CountDownLatch.h>
  24. #include <decaf/lang/Integer.h>
  25. #include <decaf/lang/Long.h>
  26. #include <decaf/lang/System.h>
  27. #include <activemq/core/ActiveMQConnectionFactory.h>
  28. #include <activemq/util/Config.h>
  29. #include <cms/Connection.h>
  30. #include <cms/Session.h>
  31. #include <cms/TextMessage.h>
  32. #include <cms/BytesMessage.h>
  33. #include <cms/MapMessage.h>
  34. #include <cms/ExceptionListener.h>
  35. #include <cms/MessageListener.h>
  36. #include <stdlib.h>
  37. #include <stdio.h>
  38. #include <iostream>
  39. #include <memory>
  40.  
  41. #include <decaf/util/Random.h>
  42.  
  43. using namespace activemq::core;
  44. using namespace decaf::util::concurrent;
  45. using namespace decaf::util;
  46. using namespace decaf::lang;
  47. using namespace cms;
  48. using namespace std;
  49.  
  50. #define QUEUE_NAME "eventQueue"
  51. #define NAME_BYTE_LEN 16
  52.  
  53. class HelloWorldProducer : public ExceptionListener,
  54. public MessageListener,
  55. public Runnable {
  56. private:
  57. CountDownLatch latch;
  58. CountDownLatch doneLatch;
  59. Connection* connection;
  60. Session* session;
  61. Destination* destination;
  62. MessageProducer* producer;
  63. int numMessages;
  64. bool useTopic;
  65. bool sessionTransacted;
  66. std::string brokerURI;
  67. bool bReciveMessage;
  68. long waitMillis;
  69.  
  70. private:
  71.  
  72. HelloWorldProducer(const HelloWorldProducer&);
  73. HelloWorldProducer& operator=(const HelloWorldProducer&);
  74.  
  75. public:
  76.  
  77. HelloWorldProducer(const std::string& brokerURI, int numMessages, bool useTopic = false, bool sessionTransacted = false,
  78. long waitMillis=3000) :
  79. latch(1),
  80. doneLatch(numMessages),
  81. connection(NULL),
  82. session(NULL),
  83. destination(NULL),
  84. producer(NULL),
  85. numMessages(numMessages),
  86. useTopic(useTopic),
  87. sessionTransacted(sessionTransacted),
  88. brokerURI(brokerURI) ,
  89. bReciveMessage(false),
  90. waitMillis(waitMillis)
  91. { }
  92.  
  93. virtual ~HelloWorldProducer(){
  94. cleanup();
  95. }
  96.  
  97. void close() {
  98. this->cleanup();
  99. }
  100.  
  101. void waitUntilReady() {
  102. latch.await();
  103. }
  104.  
  105. virtual void run() {
  106.  
  107. try {
  108.  
  109. // Create a ConnectionFactory
  110. auto_ptr<ConnectionFactory> connectionFactory(
  111. ConnectionFactory::createCMSConnectionFactory(brokerURI));
  112.  
  113. // Create a Connection
  114. connection = connectionFactory->createConnection();
  115. connection->start();
  116.  
  117. // Create a Session
  118. if (this->sessionTransacted) {
  119. session = connection->createSession(Session::SESSION_TRANSACTED);
  120. } else {
  121. session = connection->createSession(Session::AUTO_ACKNOWLEDGE);
  122. }
  123.  
  124. session = connection->createSession();
  125. // Create the destination (Topic or Queue)
  126. if (useTopic) {
  127. destination = session->createTopic(QUEUE_NAME);
  128. } else {
  129. destination = session->createQueue(QUEUE_NAME);
  130. }
  131.  
  132. // Create a MessageProducer from the Session to the Topic or Queue
  133. producer = session->createProducer(destination);
  134. producer->setDeliveryMode(DeliveryMode::NON_PERSISTENT);
  135.  
  136. // Create the Thread Id String
  137. string threadIdStr = Long::toString(Thread::currentThread()->getId());
  138.  
  139. // Create a messages
  140. string text = (string) "Hello world! from thread " + threadIdStr;
  141.  
  142. for (int ix = 0; ix < numMessages; ++ix) {
  143. std::auto_ptr<TextMessage> message(session->createTextMessage(text));
  144.  
  145. //关键消息...
  146. std::auto_ptr<Destination> tempDest(session->createTemporaryQueue());
  147.  
  148. //cms::Destination tempDest=session->createTemporaryTopic() ;
  149. MessageConsumer * responseConsumer = session->createConsumer(tempDest.get());
  150. responseConsumer->setMessageListener(this);//监听...
  151.  
  152. message->setCMSReplyTo(tempDest.get());
  153. Random random;
  154. char buffer[NAME_BYTE_LEN]={0};
  155. random.nextBytes((unsigned char *)buffer,NAME_BYTE_LEN);
  156. string correlationId="";
  157. for(int i=0;i<NAME_BYTE_LEN;++i)
  158. {
  159. char ch[NAME_BYTE_LEN*2]={0};
  160. sprintf(ch,"%02X",(unsigned char)buffer[i]);
  161. string str(ch);
  162.  
  163. correlationId+=str;
  164. }
  165.  
  166. message->setCMSCorrelationID(correlationId);
  167.  
  168. message->setIntProperty("Integer", ix);
  169. printf("Producer Sent message #%d from thread %s\n", ix + 1, threadIdStr.c_str());
  170. producer->send(message.get());
  171.  
  172. // Indicate we are ready for messages.
  173. latch.countDown();
  174.  
  175. // Wait while asynchronous messages come in.
  176. doneLatch.await(waitMillis);
  177.  
  178. }
  179. }
  180. catch (CMSException& e) {
  181. printf("Producer run() CMSException \n" );
  182. // Indicate we are ready for messages.
  183. latch.countDown();
  184. e.printStackTrace();
  185. }
  186.  
  187. }
  188.  
  189. // Called from the Producer since this class is a registered MessageListener.
  190. virtual void onMessage(const Message* message) {
  191.  
  192. static int count = 0;
  193.  
  194. try {
  195. count++;
  196. const TextMessage* textMessage = dynamic_cast<const TextMessage*> (message);
  197. //ActiveMQMessageTransformation
  198. //std::auto_ptr<TextMessage> responsemessage(session->createTextMessage());
  199. //responsemessage->setCMSCorrelationID(textMessage->getCMSCorrelationID());
  200. //responsemessage->getCMSReplyTo()
  201.  
  202. string text = "";
  203.  
  204. if (textMessage != NULL) {
  205. text = textMessage->getText();
  206. } else {
  207. text = "NOT A TEXTMESSAGE!";
  208. }
  209.  
  210. printf("Producer Message #%d Received: %s\n", count, text.c_str());
  211.  
  212. //producer.send
  213.  
  214. } catch (CMSException& e) {
  215. printf("Producer onMessage() CMSException \n" );
  216. e.printStackTrace();
  217. }
  218.  
  219. // Commit all messages.
  220. if (this->sessionTransacted) {
  221. session->commit();
  222. }
  223.  
  224. // No matter what, tag the count down latch until done.
  225. doneLatch.countDown();
  226. }
  227.  
  228. // If something bad happens you see it here as this class is also been
  229. // registered as an ExceptionListener with the connection.
  230. virtual void onException(const CMSException& ex AMQCPP_UNUSED) {
  231. printf("Producer onException() CMS Exception occurred. Shutting down client. \n" );
  232. ex.printStackTrace();
  233. exit(1);
  234. }
  235.  
  236. private:
  237.  
  238. void cleanup() {
  239.  
  240. if (connection != NULL) {
  241. try {
  242. connection->close();
  243. } catch (cms::CMSException& ex) {
  244. ex.printStackTrace();
  245. }
  246. }
  247.  
  248. // Destroy resources.
  249. try {
  250. delete destination;
  251. destination = NULL;
  252. delete producer;
  253. producer = NULL;
  254. delete session;
  255. session = NULL;
  256. delete connection;
  257. connection = NULL;
  258. } catch (CMSException& e) {
  259. e.printStackTrace();
  260. }
  261. }
  262. };
  263.  
  264. class HelloWorldConsumer : public ExceptionListener,
  265. public MessageListener,
  266. public Runnable {
  267.  
  268. private:
  269.  
  270. CountDownLatch latch;
  271. CountDownLatch doneLatch;
  272. Connection* connection;
  273. Session* session;
  274. Destination* destination;
  275. MessageConsumer* consumer;
  276. MessageProducer *producer;
  277. long waitMillis;
  278. bool useTopic;
  279. bool sessionTransacted;
  280. std::string brokerURI;
  281.  
  282. private:
  283.  
  284. HelloWorldConsumer(const HelloWorldConsumer&);
  285. HelloWorldConsumer& operator=(const HelloWorldConsumer&);
  286.  
  287. public:
  288.  
  289. HelloWorldConsumer(const std::string& brokerURI, int numMessages, bool useTopic = false, bool sessionTransacted = false, int waitMillis = 30000) :
  290. latch(1),
  291. doneLatch(numMessages),
  292. connection(NULL),
  293. session(NULL),
  294. destination(NULL),
  295. consumer(NULL),
  296. producer(NULL),
  297. waitMillis(waitMillis),
  298. useTopic(useTopic),
  299. sessionTransacted(sessionTransacted),
  300. brokerURI(brokerURI) {
  301. }
  302.  
  303. virtual ~HelloWorldConsumer() {
  304. cleanup();
  305. }
  306.  
  307. void close() {
  308. this->cleanup();
  309. }
  310.  
  311. void waitUntilReady() {
  312. latch.await();
  313. }
  314.  
  315. virtual void run() {
  316.  
  317. try {
  318.  
  319. // Create a ConnectionFactory
  320. auto_ptr<ConnectionFactory> connectionFactory(
  321. ConnectionFactory::createCMSConnectionFactory(brokerURI));
  322.  
  323. // Create a Connection
  324. connection = connectionFactory->createConnection();
  325. connection->start();
  326. connection->setExceptionListener(this);
  327.  
  328. // Create a Session
  329. if (this->sessionTransacted == true) {
  330. session = connection->createSession(Session::SESSION_TRANSACTED);
  331. } else {
  332. session = connection->createSession(Session::AUTO_ACKNOWLEDGE);
  333. }
  334.  
  335. // Create the destination (Topic or Queue)
  336. if (useTopic) {
  337. destination = session->createTopic(QUEUE_NAME);
  338. } else {
  339. destination = session->createQueue(QUEUE_NAME);
  340. }
  341.  
  342. producer = session->createProducer();
  343. producer->setDeliveryMode(DeliveryMode::NON_PERSISTENT);
  344.  
  345. // Create a MessageConsumer from the Session to the Topic or Queue
  346. consumer = session->createConsumer(destination);
  347.  
  348. consumer->setMessageListener(this);
  349.  
  350. std::cout.flush();
  351. std::cerr.flush();
  352.  
  353. // Indicate we are ready for messages.
  354. latch.countDown();
  355.  
  356. // Wait while asynchronous messages come in.
  357. doneLatch.await();
  358.  
  359. } catch (CMSException& e) {
  360. printf("Consumer onException() CMS Exception occurred. Shutting down client. \n" );
  361. // Indicate we are ready for messages.
  362. latch.countDown();
  363. e.printStackTrace();
  364. }
  365. }
  366.  
  367. // Called from the consumer since this class is a registered MessageListener.
  368. virtual void onMessage(const Message* message) {
  369.  
  370. static int count = 0;
  371.  
  372. try {
  373. count++;
  374.  
  375. // Create the Thread Id String
  376. string threadIdStr = Long::toString(Thread::currentThread()->getId());
  377.  
  378. static bool bPrintf=true;
  379. if(bPrintf)
  380. {
  381. bPrintf=false;
  382. printf("consumer Message threadid: %s\n", threadIdStr.c_str());
  383. }
  384.  
  385. string strReply="consumer return xxx,ThreadID="+threadIdStr;
  386. const TextMessage* textMessage = dynamic_cast<const TextMessage*> (message);
  387.  
  388. if(NULL==textMessage)
  389. {
  390. printf("NULL==textMessage", message->getCMSType().c_str());
  391.  
  392. //const cms::MapMessage* mapMsg = dynamic_cast<const cms::MapMessage*>(message);
  393. //if(mapMsg)
  394. //{
  395. //
  396. // std::vector<std::string> elements = mapMsg->getMapNames();
  397. // std::vector<std::string>::iterator iter = elements.begin();
  398. // for(; iter != elements.end() ; ++iter)
  399. // {
  400. // std::string key = *iter;
  401. // cms::Message::ValueType elementType = mapMsg->getValueType(key);
  402. // string strxxx;
  403. // int cc=0;
  404. // switch(elementType) {
  405. // case cms::Message::BOOLEAN_TYPE:
  406. // //msg->setBoolean(key, mapMsg->getBoolean(key));
  407. // break;
  408. // case cms::Message::BYTE_TYPE:
  409. // //msg->setByte(key, mapMsg->getByte(key));
  410. // break;
  411. // case cms::Message::BYTE_ARRAY_TYPE:
  412. // //msg->setBytes(key, mapMsg->getBytes(key));
  413. // break;
  414. // case cms::Message::CHAR_TYPE:
  415. // //msg->setChar(key, mapMsg->getChar(key));
  416. // break;
  417. // case cms::Message::SHORT_TYPE:
  418. // //msg->setShort(key, mapMsg->getShort(key));
  419. // break;
  420. // case cms::Message::INTEGER_TYPE:
  421. // //msg->setInt(key, mapMsg->getInt(key));
  422. // break;
  423. // case cms::Message::LONG_TYPE:
  424. // //msg->setLong(key, mapMsg->getLong(key));
  425. // break;
  426. // case cms::Message::FLOAT_TYPE:
  427. // //msg->setFloat(key, mapMsg->getFloat(key));
  428. // break;
  429. // case cms::Message::DOUBLE_TYPE:
  430. // //msg->setDouble(key, mapMsg->getDouble(key));
  431. // break;
  432. // case cms::Message::STRING_TYPE:
  433. // //msg->setString(key, mapMsg->getString(key));
  434. // strxxx=mapMsg->getString(key);
  435. // cc=1;
  436. // break;
  437. // default:
  438. // break;
  439. // }
  440. // }
  441.  
  442. //}
  443.  
  444. return;
  445. }
  446.  
  447. std::auto_ptr<TextMessage> responsemessage(session->createTextMessage(strReply));
  448. responsemessage->setCMSCorrelationID(textMessage->getCMSCorrelationID());
  449.  
  450. string text = "";
  451.  
  452. if (textMessage != NULL) {
  453. text = textMessage->getText();
  454. } else {
  455. text = "NOT A TEXTMESSAGE!";
  456. }
  457.  
  458. int nProPerty=textMessage->getIntProperty("Integer");
  459. printf("consumer Message #%d Received: %s,nProPerty[%d]\n", count, text.c_str(),nProPerty);
  460.  
  461. const cms::Destination* destSend=textMessage->getCMSReplyTo();
  462. if(destSend)
  463. {
  464. this->producer->send(destSend,responsemessage.get());
  465.  
  466. printf("consumer Message #%d send: %s\n", count, strReply.c_str());
  467. }
  468.  
  469. } catch (CMSException& e) {
  470. printf("Consumer onMessage() CMS Exception occurred. Shutting down client. \n" );
  471. e.printStackTrace();
  472. }
  473.  
  474. // Commit all messages.
  475. if (this->sessionTransacted) {
  476. session->commit();
  477. }
  478.  
  479. // No matter what, tag the count down latch until done.
  480. //doneLatch.countDown();
  481. }
  482.  
  483. // If something bad happens you see it here as this class is also been
  484. // registered as an ExceptionListener with the connection.
  485. virtual void onException(const CMSException& ex AMQCPP_UNUSED) {
  486. printf("Consumer onException() CMS Exception occurred. Shutting down client. \n" );
  487. //printf("CMS Exception occurred. Shutting down client.\n");
  488. ex.printStackTrace();
  489. exit(1);
  490. }
  491.  
  492. private:
  493.  
  494. void cleanup() {
  495. if (connection != NULL) {
  496. try {
  497. connection->close();
  498. } catch (cms::CMSException& ex) {
  499. ex.printStackTrace();
  500. }
  501. }
  502.  
  503. // Destroy resources.
  504. try {
  505. delete destination;
  506. destination = NULL;
  507. delete consumer;
  508. consumer = NULL;
  509. delete session;
  510. session = NULL;
  511. delete connection;
  512. connection = NULL;
  513. } catch (CMSException& e) {
  514. e.printStackTrace();
  515. }
  516. }
  517. };
  518.  
  519. int main(int argc AMQCPP_UNUSED, char* argv[] AMQCPP_UNUSED) {
  520.  
  521. //if(argc<)
  522. //{
  523. // printf("argc<2\r\n");
  524. // return 0;
  525. //}
  526.  
  527. activemq::library::ActiveMQCPP::initializeLibrary();
  528. {
  529. std::cout << "=====================================================\n";
  530. std::cout << "Starting the example:" << std::endl;
  531. std::cout << "-----------------------------------------------------\n";
  532.  
  533. // Set the URI to point to the IP Address of your broker.
  534. // add any optional params to the url to enable things like
  535. // tightMarshalling or tcp logging etc. See the CMS web site for
  536. // a full list of configuration options.
  537. //
  538. // http://activemq.apache.org/cms/
  539. //
  540. // Wire Format Options:
  541. // =========================
  542. // Use either stomp or openwire, the default ports are different for each
  543. //
  544. // Examples:
  545. // tcp://127.0.0.1:61616 default to openwire
  546. // tcp://127.0.0.1:61616?wireFormat=openwire same as above
  547. // tcp://127.0.0.1:61613?wireFormat=stomp use stomp instead
  548. //
  549. // SSL:
  550. // =========================
  551. // To use SSL you need to specify the location of the trusted Root CA or the
  552. // certificate for the broker you want to connect to. Using the Root CA allows
  553. // you to use failover with multiple servers all using certificates signed by
  554. // the trusted root. If using client authentication you also need to specify
  555. // the location of the client Certificate.
  556. //
  557. // System::setProperty( "decaf.net.ssl.keyStore", "<path>/client.pem" );
  558. // System::setProperty( "decaf.net.ssl.keyStorePassword", "password" );
  559. // System::setProperty( "decaf.net.ssl.trustStore", "<path>/rootCA.pem" );
  560. //
  561. // The you just specify the ssl transport in the URI, for example:
  562. //
  563. // ssl://localhost:61617
  564. //
  565. std::string brokerURI =
  566. "failover:(tcp://192.168.10.143:61616"
  567. // "?wireFormat=openwire"
  568. // "&transport.useInactivityMonitor=false"
  569. // "&connection.alwaysSyncSend=true"
  570. // "&connection.useAsyncSend=true"
  571. // "?transport.commandTracingEnabled=true"
  572. // "&transport.tcpTracingEnabled=true"
  573. // "&wireFormat.tightEncodingEnabled=true"
  574. ")";
  575.  
  576. //============================================================
  577. // set to true to use topics instead of queues
  578. // Note in the code above that this causes createTopic or
  579. // createQueue to be used in both consumer an producer.
  580. //============================================================
  581. bool useTopics = false;
  582. bool sessionTransacted = true;
  583. int numMessages = 1;
  584. bool useConsumer=true;
  585. bool useProducer=true;
  586.  
  587. //int nSet=atoi(argv[1]);
  588. //if(1==nSet)
  589. //{
  590. //#define USE_COMSUMER
  591.  
  592. //}
  593. //else
  594. //{
  595. //#define USE_PRODUCER
  596.  
  597. //
  598. //}
  599.  
  600. long long startTime = System::currentTimeMillis();
  601.  
  602. #ifdef USE_PRODUCER
  603. printf("当前 USE_PRODUCER \r\n");
  604.  
  605. int numProducerMessages = 30;
  606. int nThreadNumber=10;
  607. vector<HelloWorldProducer *> vHelloWorldProducer;
  608. for(int i=0;i<nThreadNumber;++i)
  609. {
  610. HelloWorldProducer * producerTemp=new HelloWorldProducer(brokerURI, numProducerMessages, useTopics);
  611. vHelloWorldProducer.push_back(producerTemp);
  612. }
  613.  
  614. #endif
  615.  
  616. #ifdef USE_COMSUMER
  617. printf("当前 USE_COMSUMER \r\n");
  618. HelloWorldConsumer consumer(brokerURI, numMessages, useTopics, sessionTransacted);
  619. // Start the consumer thread.
  620. Thread consumerThread(&consumer);
  621. consumerThread.start();
  622.  
  623. // Wait for the consumer to indicate that its ready to go.
  624. consumer.waitUntilReady();
  625.  
  626. #endif
  627.  
  628. #ifdef USE_PRODUCER
  629. // Start the producer thread.
  630.  
  631. vector<Thread *> vThread;
  632. for(int i=0;i<nThreadNumber;++i)
  633. {
  634. HelloWorldProducer & ProducerTemp=*vHelloWorldProducer[i];
  635. Thread * threadTemp=new Thread(&ProducerTemp);
  636. vThread.push_back(threadTemp);
  637. threadTemp->start();
  638. ProducerTemp.waitUntilReady();
  639.  
  640. }
  641.  
  642. for(int i=0;i<vThread.size();++i)
  643. {
  644. Thread * threadTemp=vThread[i];
  645. //threadTemp->join();
  646. }
  647. while(1)
  648. {
  649. Thread::sleep(10);
  650. }
  651.  
  652. //Thread producerThread1(&producer1);
  653. //producerThread1.start();
  654. //producer1.waitUntilReady();
  655.  
  656. //Thread producerThread2(&producer2);
  657. //producerThread2.start();
  658. //producer2.waitUntilReady();
  659.  
  660. //Thread producerThread3(&producer3);
  661. //producerThread3.start();
  662. //producer3.waitUntilReady();
  663. #endif
  664.  
  665. #ifdef USE_PRODUCER
  666. // Wait for the threads to complete.
  667. //producerThread1.join();
  668. //producerThread2.join();
  669. //producerThread3.join();
  670. #endif
  671.  
  672. #ifdef USE_COMSUMER
  673. consumerThread.join();
  674. #endif
  675.  
  676. long long endTime = System::currentTimeMillis();
  677. double totalTime = (double)(endTime - startTime) / 1000.0;
  678.  
  679. #ifdef USE_PRODUCER
  680. //producer1.close();
  681. //producer2.close();
  682. //producer3.close();
  683.  
  684. for(int i=0;i<vHelloWorldProducer.size();++i)
  685. {
  686. HelloWorldProducer * ProducerTemp=vHelloWorldProducer[i];
  687. ProducerTemp->close();
  688.  
  689. if(ProducerTemp)
  690. {
  691. delete ProducerTemp;
  692. ProducerTemp=NULL;
  693. }
  694. }
  695.  
  696. #endif
  697. #ifdef USE_COMSUMER
  698. consumer.close();
  699. #endif
  700.  
  701. std::cout << "Time to completion = " << totalTime << " seconds." << std::endl;
  702. std::cout << "-----------------------------------------------------\n";
  703. std::cout << "Finished with the example." << std::endl;
  704. std::cout << "=====================================================\n";
  705.  
  706. }
  707. activemq::library::ActiveMQCPP::shutdownLibrary();
  708.  
  709. return 0;
  710. }
  711.  
  712. // END SNIPPET: demo

程序运行结果:

关于activemq-cpp 的Message 消息转换.

activemq-cpp 中的转换ActiveMQMessageTransformation.transformMessage 中是有相应的实现.

  1. ////////////////////////////////////////////////////////////////////////////////
  2. bool ActiveMQMessageTransformation::transformMessage(cms::Message* message, ActiveMQConnection* connection, Message** amqMessage) {
  3.  
  4. if (message == NULL) {
  5. throw NullPointerException(__FILE__, __LINE__, "Provided source cms::Message pointer was NULL");
  6. }
  7.  
  8. if (amqMessage == NULL) {
  9. throw NullPointerException(__FILE__, __LINE__, "Provided target commands::Message pointer was NULL");
  10. }
  11.  
  12. *amqMessage = dynamic_cast<Message*>(message);
  13.  
  14. if (*amqMessage != NULL) {
  15. return false;
  16. } else {
  17.  
  18. if (dynamic_cast<cms::BytesMessage*>(message) != NULL) {
  19. cms::BytesMessage* bytesMsg = dynamic_cast<cms::BytesMessage*>(message);
  20. bytesMsg->reset();
  21. ActiveMQBytesMessage* msg = new ActiveMQBytesMessage();
  22. msg->setConnection(connection);
  23. try {
  24. for (;;) {
  25. // Reads a byte from the message stream until the stream is empty
  26. msg->writeByte(bytesMsg->readByte());
  27. }
  28. } catch (cms::MessageEOFException& e) {
  29. // if an end of message stream as expected
  30. } catch (cms::CMSException& e) {
  31. }
  32.  
  33. *amqMessage = msg;
  34. } else if (dynamic_cast<cms::MapMessage*>(message) != NULL) {
  35. cms::MapMessage* mapMsg = dynamic_cast<cms::MapMessage*>(message);
  36. ActiveMQMapMessage* msg = new ActiveMQMapMessage();
  37. msg->setConnection(connection);
  38.  
  39. std::vector<std::string> elements = mapMsg->getMapNames();
  40. std::vector<std::string>::iterator iter = elements.begin();
  41. for(; iter != elements.end() ; ++iter) {
  42. std::string key = *iter;
  43. cms::Message::ValueType elementType = mapMsg->getValueType(key);
  44.  
  45. switch(elementType) {
  46. case cms::Message::BOOLEAN_TYPE:
  47. msg->setBoolean(key, mapMsg->getBoolean(key));
  48. break;
  49. case cms::Message::BYTE_TYPE:
  50. msg->setByte(key, mapMsg->getByte(key));
  51. break;
  52. case cms::Message::BYTE_ARRAY_TYPE:
  53. msg->setBytes(key, mapMsg->getBytes(key));
  54. break;
  55. case cms::Message::CHAR_TYPE:
  56. msg->setChar(key, mapMsg->getChar(key));
  57. break;
  58. case cms::Message::SHORT_TYPE:
  59. msg->setShort(key, mapMsg->getShort(key));
  60. break;
  61. case cms::Message::INTEGER_TYPE:
  62. msg->setInt(key, mapMsg->getInt(key));
  63. break;
  64. case cms::Message::LONG_TYPE:
  65. msg->setLong(key, mapMsg->getLong(key));
  66. break;
  67. case cms::Message::FLOAT_TYPE:
  68. msg->setFloat(key, mapMsg->getFloat(key));
  69. break;
  70. case cms::Message::DOUBLE_TYPE:
  71. msg->setDouble(key, mapMsg->getDouble(key));
  72. break;
  73. case cms::Message::STRING_TYPE:
  74. msg->setString(key, mapMsg->getString(key));
  75. break;
  76. default:
  77. break;
  78. }
  79. }
  80.  
  81. *amqMessage = msg;
  82. } else if (dynamic_cast<cms::ObjectMessage*>(message) != NULL) {
  83. cms::ObjectMessage* objMsg = dynamic_cast<cms::ObjectMessage*>(message);
  84. ActiveMQObjectMessage* msg = new ActiveMQObjectMessage();
  85. msg->setConnection(connection);
  86. msg->setObjectBytes(objMsg->getObjectBytes());
  87. *amqMessage = msg;
  88. } else if (dynamic_cast<cms::StreamMessage*>(message) != NULL) {
  89. cms::StreamMessage* streamMessage = dynamic_cast<cms::StreamMessage*>(message);
  90. streamMessage->reset();
  91. ActiveMQStreamMessage* msg = new ActiveMQStreamMessage();
  92. msg->setConnection(connection);
  93.  
  94. try {
  95. while(true) {
  96. cms::Message::ValueType elementType = streamMessage->getNextValueType();
  97. int result = -1;
  98. std::vector<unsigned char> buffer(255);
  99.  
  100. switch(elementType) {
  101. case cms::Message::BOOLEAN_TYPE:
  102. msg->writeBoolean(streamMessage->readBoolean());
  103. break;
  104. case cms::Message::BYTE_TYPE:
  105. msg->writeBoolean(streamMessage->readBoolean());
  106. break;
  107. case cms::Message::BYTE_ARRAY_TYPE:
  108. while ((result = streamMessage->readBytes(buffer)) != -1) {
  109. msg->writeBytes(&buffer[0], 0, result);
  110. buffer.clear();
  111. }
  112. break;
  113. case cms::Message::CHAR_TYPE:
  114. msg->writeChar(streamMessage->readChar());
  115. break;
  116. case cms::Message::SHORT_TYPE:
  117. msg->writeShort(streamMessage->readShort());
  118. break;
  119. case cms::Message::INTEGER_TYPE:
  120. msg->writeInt(streamMessage->readInt());
  121. break;
  122. case cms::Message::LONG_TYPE:
  123. msg->writeLong(streamMessage->readLong());
  124. break;
  125. case cms::Message::FLOAT_TYPE:
  126. msg->writeFloat(streamMessage->readFloat());
  127. break;
  128. case cms::Message::DOUBLE_TYPE:
  129. msg->writeDouble(streamMessage->readDouble());
  130. break;
  131. case cms::Message::STRING_TYPE:
  132. msg->writeString(streamMessage->readString());
  133. break;
  134. default:
  135. break;
  136. }
  137. }
  138. } catch (cms::MessageEOFException& e) {
  139. // if an end of message stream as expected
  140. } catch (cms::CMSException& e) {
  141. }
  142.  
  143. *amqMessage = msg;
  144. } else if (dynamic_cast<cms::TextMessage*>(message) != NULL) {
  145. cms::TextMessage* textMsg = dynamic_cast<cms::TextMessage*>(message);
  146. ActiveMQTextMessage* msg = new ActiveMQTextMessage();
  147. msg->setConnection(connection);
  148. msg->setText(textMsg->getText());
  149. *amqMessage = msg;
  150. } else {
  151. *amqMessage = new ActiveMQMessage();
  152. (*amqMessage)->setConnection(connection);
  153. }
  154.  
  155. ActiveMQMessageTransformation::copyProperties(message, dynamic_cast<cms::Message*>(*amqMessage));
  156. }
  157.  
  158. return true;
  159. }

5,activemq 的activemq broker cluster (activemq 集群).

可以参考:

http://bh-keven.iteye.com/blog/1617788

http://blog.csdn.net/jason5186/article/details/18702523

6,activemq.xml 中的配置和activemq Connection URIS 配置

http://activemq.apache.org/nms/activemq-uri-configuration.html

http://activemq.apache.org/tcp-transport-reference.html

是有相应介绍,但需要花一些时间去读.

//7,wireFormat=openwire 的几种方式.的优缺点.

//openwire,amqp,stomp,mqtt,ws

C++ activemq CMS 学习笔记.的更多相关文章

  1. ActiveMQ学习笔记(5)——使用Spring JMS收发消息

      摘要 ActiveMQ学习笔记(四)http://my.oschina.net/xiaoxishan/blog/380446 中记录了如何使用原生的方式从ActiveMQ中收发消息.可以看出,每次 ...

  2. CUBRID学习笔记 2 安装教程

    下载地址  http://www.cubrid.org/?mid=downloads&item=any&os=detect&cubrid=9.3.0 选择适合你的服务器版本 l ...

  3. SQLite介绍、学习笔记、性能测试

    SQLite介绍.学习笔记.性能测试 哪些人,哪些公司或软件在用SQLite: Nokia's Symbian,Mozilla,Abobe,Google,阿里旺旺,飞信,Chrome,FireFox可 ...

  4. GC学习笔记

    GC学习笔记 这是我公司同事的GC学习笔记,写得蛮详细的,由浅入深,循序渐进,让人一看就懂,特转到这里. 一.GC特性以及各种GC的选择 1.垃圾回收器的特性 2.对垃圾回收器的选择 2.1 连续 V ...

  5. 非常详细GC学习笔记

    转载:http://blog.csdn.net/fenglibing/article/details/6321453 这是我公司同事的GC学习笔记,写得蛮详细的,由浅入深,循序渐进,让人一看就懂,特转 ...

  6. 【转】Spring.NET学习笔记——目录

    目录 前言 Spring.NET学习笔记——前言 第一阶段:控制反转与依赖注入IoC&DI Spring.NET学习笔记1——控制反转(基础篇) Level 200 Spring.NET学习笔 ...

  7. 很具体GC学习笔记

    GC学习笔记 这是我公司同事的GC学习笔记,写得蛮具体的,由浅入深,循序渐进,让人一看就懂,特转到这里. 一.GC特性以及各种GC的选择 1.垃圾回收器的特性 2.对垃圾回收器的选择 2.1 连续 V ...

  8. 一个.NET Core开发者的Linux入门学习笔记

    用.NET Core开发也有一段时间了,但是由于工作原因一直都是在Windows系统上进行的开发,一直想学习Linux然后把.NET Core开发的程序跑在Linux上,然后把心得体会记录一下发布再博 ...

  9. 【Java虚拟机】JVM学习笔记之GC

    JVM学习笔记二之GC GC即垃圾回收,在C++中垃圾回收由程序员自己来做,例如可以用free和delete来回收对象.而在Java中,JVM替程序员来执行垃圾回收的工作,下面看看GC的详细原理和执行 ...

随机推荐

  1. docker笔记

    安装...不说了 docker info 查看信息 docker pull ...拉取镜像 docker run -it [镜像名] 运行 docker ps查看当前运行的容器  docker ps ...

  2. 编写高质量代码:改善Java程序的建议

    建议的采用顺序是List<T>.List<?>.List<Object> List<T>.List<?>.List<Object> ...

  3. Winform的"透明"

    手头目前的一个项目(.Net4.0)中有这样一个需求:在程序中要进行视频采集,并且要在视频影像区域进行绘图编辑,对绘图能进行拉伸,拖拽和删除.从需求来看,必须得在视频影像区的上方盖一层画布才能这么操作 ...

  4. Java_File类讲解_打印目录树状结构_递归算法

    package cn.xiaocangtian.testFile; import java.io.File; public class FileTree { public static void ma ...

  5. iOS 申请加急审核

    申请加急网址:https://developer.apple.com/appstore/contact/appreviewteam/index.html 提交加急审核需要理由,一般涉及到银行信息,或者 ...

  6. 三层架构的OPP实现的演示例子

    例子:演示会员添加与删除 说明:因为是简单的例子,我们用在屏幕上打印"添加成功"和"删除成功"这几个字表示会员的添加与删除,仅仅为了演示如何实现三层的分离: 1 ...

  7. android studio使用ndk,jni随记

    1.下载ndk(会下载到sdk目录下) 2.配置 3.配置build.gradle(app) android { defaultConfig { ndk { moduleName "JniD ...

  8. 实现滑动可固定header以及页面刷新

    用到的布局:SwiperRefreshLayout,AppBarLayout,ToolBar,CollapsingToolbarLayout,CoordinatorLayout 布局 <?xml ...

  9. Mysql中eft join、right join、inner join的区别

    left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录inner join(等值连接) 只 ...

  10. C# ADO.net 数据库连接池

    前一阵开发一套系统,同组的同事提供了一个数据库连接组件,是他自己封装的,使用了自定义的连接池,用着很是不爽,而且经常会因为程序不严谨的原因,导致连接池里的连接被用完,也导致其他错误,因此我想自己研究一 ...