当前位置:   article > 正文

Qt中使用RabbitMQ-c(一):使用CMake + MinGW编译RabbitMQ-c_qt rabbitmq-c

qt rabbitmq-c

      项目需要,在发送和接受数据的时候使用RabbitMQ队列作为中间基站。想要对RabbitMQ有个基本的了解,可以结合官网:http://www.rabbitmq.com/,和这篇博客:http://blog.csdn.net/anzhsoft/article/details/19563091一起来理解。

      因为是在Qt中使用,所以需要用RabbitMQ-c,官网没有c语言使用RabbitMQ的详细介绍,上面的博客是使用Python来作为说明的,所以还需另寻他路,自己琢磨琢磨。

      准备工作:

      1、使用Qt 4.7.4和Qt Creator 2.4.1及其的MinGW:

            具体的下载安装请见另一篇博客:Qt中使用Protocol Buffers(一):使用QT的MinGW + msys编译Protocol Buffers v2.6.1

      2、Cmak:

            下载:https://cmake.org/download/,当前最新版本3.8.0,下载cmake-3.8.0-win64-x64.zip

            安装:解压并将bin目录添加到环境目录中去,安装成功后可以在cmd中输入cmake --version查看cmake的版本,cmake --help查看cmake的帮助

            

            

      3、RabbitMQ-c:

            下载:GitHub上下载:https://github.com/alanxz/rabbitmq-c/,下载rabbitmq-c-master.zip,下载完后解压,就可以开始编译啦

      开始编译:

     根据RabbitMQ-c的下载地址下面的说明文档进行编译

      1、使用cmd进入到RabbitMQ的解压地址,在rabbitmq-c-master文件夹中的cmake文件夹中创建文件夹build,然后输入cmake -G "MinGW Makefiles" -DCMAKE_INSTALL_PREFIX=../../install ../..来配置

            cmake表示命令

            -G "MinGW Makefiles"表示使用MinGW来生成文件

            -DCMAKE_INSTALL_PREFIX=../../install表示在rabbitmq-c-master文件夹中创建(如果没有)install文件夹,并在install的时候将文件存放其中。

            ../..表示CmakeLists.txt所在的文件夹rabbitmq-c-master的文件夹

            配置结果:

            

            在这一步的时候遇到两个错误:

            Error1: could not find cmakeroot,解决办法:重新安装cmake

            Error2: could not find openssl:

            

            解决办法在这个网站找到:https://zhidao.baidu.com/question/587845628097951765.html,即将CMakeLists.txt文件中的ENABLE_SSL_SUPPORT的ON改成OFF,再删除之前生成的文件重新编译。

            正确的编译结果是:

            D:\RabbitMQ\rabbitmq-c-master\cmake\build>cmake -G "MinGW Makefiles" -DCMAKE_INSTALL_PREFIX=../../install ../..
            -- The C compiler identification is GNU 4.4.0
            -- Check for working C compiler: D:/Qt/qtcreator-2.4.1/mingw/bin/gcc.exe
            -- Check for working C compiler: D:/Qt/qtcreator-2.4.1/mingw/bin/gcc.exe -- works
            -- Detecting C compiler ABI info
            -- Detecting C compiler ABI info - done
            -- Detecting C compile features
            -- Detecting C compile features - done
            -- CMAKE_BUILD_TYPE not specified. Creating Release build
            -- Found C inline keyword: inline
            -- Looking for htonll
            -- Looking for htonll - not found
            -- Looking for poll
            -- Looking for poll - not found
            -- Looking for clock_gettime in rt
            -- Looking for clock_gettime in rt - not found
            -- Looking for posix_spawnp in rt
            -- Looking for posix_spawnp in rt - not found
            -- Performing Test HAVE_GNU90
            -- Performing Test HAVE_GNU90 - Failed
            -- Performing Test HAVE_C90
            -- Performing Test HAVE_C90 - Failed
            -- Could NOT find POPT (missing:  POPT_INCLUDE_DIR POPT_LIBRARY)
            -- Could NOT find XMLTO (missing:  XMLTO_EXECUTABLE)
            -- Could NOT find Doxygen (missing:  DOXYGEN_EXECUTABLE)
            -- Looking for pthread.h
            -- Looking for pthread.h - found
            -- Looking for pthread_create
            -- Looking for pthread_create - not found
            -- Looking for pthread_create in pthreads
            -- Looking for pthread_create in pthreads - not found
            -- Looking for pthread_create in pthread
            -- Looking for pthread_create in pthread - found
            -- Found Threads: TRUE
            -- Building rabbitmq as a shared library - yes
            -- Building rabbitmq as a static library - yes
            -- Configuring done
            -- Generating done
            -- Build files have been written to: D:/RabbitMQ/rabbitmq-c-master/cmake/build

      2、配置成功后就是编译make,输入make

      3、编译成功后就是安装,输入make install:

            如果安装成功后再次输入make install就是如下内容:

            

      4、安装成功,可以在install文件夹中查找到以下内容:

            bin文件夹:librabbitmq.4.dll

            include文件夹:amqp.h、amqp_framing.h、amqp_tcp_socket.h

            lib文件夹:liblibrabbitmq.4.a、librabbitmq.4.dll.a

      简单实例:(测试安装是否成功)

      依然是根据GitHub上面的安装教程,后面接着的running the examples,不过它是用cmd命令行运行的,我直接在Qt中使用。

      1、分别建两个工程,控制台类型,一个用来发送一个用来监听

      2、分别在每个工程文件的文件夹里添加上三个头文件:amqp.h、amqp_framing.h、amqp_tcp_socket.h和一个静态库文件:librabbitmq.4.dll.a

      3、分别在每个工程的.pro文件中添加

LIBS += -L$$PWD/ -lrabbitmq.4
      “-L$$PWD”是当前目录,即main.cpp所在目录,因为我的librabbitmq.4.dll.a放在当前目录中,所以直接这么写就可以,注意:/后面可以有空格,但是-l和文件之间不能有空格,且文件名中的lib和.dll.a皆省略。

      4、编译运行文件会发现不成功,但会生成一个工程文件夹,将librabbitmq.4.dll文件添加到生成的工程文件夹中的debug文件夹中去,再次编译运行即

      运行结果:

      

      运行出现的错误:

      Logging in:socket is closed,两个可能:

      1、检查hostname、prot、exchange、routingkey / bindingkey、user、psw,可能笔误写错。

      2、主机的服务器没有开启,导致socket is closed,本例是使用localhost作为服务器,所以还需要在本地下载RabbitMQ的服务端,并打开使用才能成功运行。            

      rabbitmq-c的使用说明:

      1、需要有主机名:hostname、端口号:port、交换机:exchange、路由钥匙:routingkey / 绑定钥匙:bindingkey、用户名:user、密码:psw,我们的实例中默认用户名和密码都是guest。

      2、先建立TCP连接:

  1. conn = amqp_new_connection();
  2. socket = amqp_tcp_socket_new(conn);

      3、打开建立的TCP连接,使用socket,主机名和端口号:

status = amqp_socket_open(socket, hostname, port);
      4、登录:

amqp_login(conn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, "guest", "guest");
      5、打开信道:

  1. amqp_channel_open(conn, 1);
  2. amqp_get_rpc_reply(conn);
      6、开始发送或者监听消息

      7、关闭信道、关闭连接、销毁连接:

  1. amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
  2. amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
  3. amqp_destroy_connection(conn);

      发送和监听的main.cpp文件分别是: 

  1. //发送"Hello World!”消息
  2. #include <QtCore/QCoreApplication>
  3. #include <QDebug>
  4. //RabbitMQ相关头文件
  5. #include "amqp.h"
  6. #include "amqp_framing.h"
  7. #include "amqp_tcp_socket.h"
  8. void die_on_error(int x, char const *context)
  9. {
  10. if (x < 0) {
  11. fprintf(stderr, "%s: %s\n", context, amqp_error_string2(x));
  12. exit(1);
  13. }
  14. }
  15. void die_on_amqp_error(amqp_rpc_reply_t x, char const *context)
  16. {
  17. switch (x.reply_type) {
  18. case AMQP_RESPONSE_NORMAL:
  19. return;
  20. case AMQP_RESPONSE_NONE:
  21. fprintf(stderr, "%s: missing RPC reply type!\n", context);
  22. break;
  23. case AMQP_RESPONSE_LIBRARY_EXCEPTION:
  24. fprintf(stderr, "%s: %s\n", context, amqp_error_string2(x.library_error));
  25. break;
  26. case AMQP_RESPONSE_SERVER_EXCEPTION:
  27. switch (x.reply.id) {
  28. case AMQP_CONNECTION_CLOSE_METHOD: {
  29. amqp_connection_close_t *m = (amqp_connection_close_t *) x.reply.decoded;
  30. fprintf(stderr, "%s: server connection error %uh, message: %.*s\n",
  31. context,
  32. m->reply_code,
  33. (int) m->reply_text.len, (char *) m->reply_text.bytes);
  34. break;
  35. }
  36. case AMQP_CHANNEL_CLOSE_METHOD: {
  37. amqp_channel_close_t *m = (amqp_channel_close_t *) x.reply.decoded;
  38. fprintf(stderr, "%s: server channel error %uh, message: %.*s\n",
  39. context,
  40. m->reply_code,
  41. (int) m->reply_text.len, (char *) m->reply_text.bytes);
  42. break;
  43. }
  44. default:
  45. fprintf(stderr, "%s: unknown server error, method id 0x%08X\n", context, x.reply.id);
  46. break;
  47. }
  48. break;
  49. }
  50. exit(1);
  51. }
  52. int main(int argc, char *argv[])
  53. {
  54. QCoreApplication a(argc, argv);
  55. //RabbitMQ start
  56. char const *hostname;
  57. int port, status;
  58. char const *exchange;
  59. char const *routingkey;
  60. char const *messagebody;
  61. amqp_socket_t *socket;
  62. amqp_connection_state_t conn;
  63. hostname = "localhost";
  64. port = 5672;
  65. exchange = "amq.direct";
  66. routingkey = "test";
  67. messagebody = "Hello World!";
  68. conn = amqp_new_connection();
  69. socket = amqp_tcp_socket_new(conn);
  70. if (!socket) {
  71. qDebug() << "creating TCP socket";
  72. }
  73. status = amqp_socket_open(socket, hostname, port);
  74. if (status) {
  75. qDebug() << "opening TCP socket";
  76. }
  77. die_on_amqp_error(amqp_login(conn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, "guest", "guest"),
  78. "Logging in");
  79. amqp_channel_open(conn, 1);
  80. die_on_amqp_error(amqp_get_rpc_reply(conn), "Opening channel");
  81. {
  82. amqp_basic_properties_t props;
  83. props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG;
  84. props.content_type = amqp_cstring_bytes("text/plain");
  85. props.delivery_mode = 2; /* persistent delivery mode */
  86. die_on_error(amqp_basic_publish(conn,
  87. 1,
  88. amqp_cstring_bytes(exchange),
  89. amqp_cstring_bytes(routingkey),
  90. 0,
  91. 0,
  92. &props,
  93. amqp_cstring_bytes(messagebody)),
  94. "Publishing");
  95. }
  96. die_on_amqp_error(amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS), "Closing channel");
  97. die_on_amqp_error(amqp_connection_close(conn, AMQP_REPLY_SUCCESS), "Closing connection");
  98. die_on_error(amqp_destroy_connection(conn), "Ending connection");
  99. //RabbitMQ end
  100. return a.exec();
  101. }

  1. //监听“Hello World!”消息
  2. #include <QtCore/QCoreApplication>
  3. #include <QDebug>
  4. //RabbitMQ相关头文件
  5. #include "amqp.h"
  6. #include "amqp_framing.h"
  7. #include "amqp_tcp_socket.h"
  8. void die_on_error(int x, char const *context)
  9. {
  10. if (x < 0) {
  11. fprintf(stderr, "%s: %s\n", context, amqp_error_string2(x));
  12. exit(1);
  13. }
  14. }
  15. void die_on_amqp_error(amqp_rpc_reply_t x, char const *context)
  16. {
  17. switch (x.reply_type) {
  18. case AMQP_RESPONSE_NORMAL:
  19. return;
  20. case AMQP_RESPONSE_NONE:
  21. fprintf(stderr, "%s: missing RPC reply type!\n", context);
  22. break;
  23. case AMQP_RESPONSE_LIBRARY_EXCEPTION:
  24. fprintf(stderr, "%s: %s\n", context, amqp_error_string2(x.library_error));
  25. break;
  26. case AMQP_RESPONSE_SERVER_EXCEPTION:
  27. switch (x.reply.id) {
  28. case AMQP_CONNECTION_CLOSE_METHOD: {
  29. amqp_connection_close_t *m = (amqp_connection_close_t *) x.reply.decoded;
  30. fprintf(stderr, "%s: server connection error %uh, message: %.*s\n",
  31. context,
  32. m->reply_code,
  33. (int) m->reply_text.len, (char *) m->reply_text.bytes);
  34. break;
  35. }
  36. case AMQP_CHANNEL_CLOSE_METHOD: {
  37. amqp_channel_close_t *m = (amqp_channel_close_t *) x.reply.decoded;
  38. fprintf(stderr, "%s: server channel error %uh, message: %.*s\n",
  39. context,
  40. m->reply_code,
  41. (int) m->reply_text.len, (char *) m->reply_text.bytes);
  42. break;
  43. }
  44. default:
  45. fprintf(stderr, "%s: unknown server error, method id 0x%08X\n", context, x.reply.id);
  46. break;
  47. }
  48. break;
  49. }
  50. exit(1);
  51. }
  52. static void dump_row(long count, int numinrow, int *chs)
  53. {
  54. int i;
  55. printf("%08lX:", count - numinrow);
  56. if (numinrow > 0) {
  57. for (i = 0; i < numinrow; i++) {
  58. if (i == 8) {
  59. printf(" :");
  60. }
  61. printf(" %02X", chs[i]);
  62. }
  63. for (i = numinrow; i < 16; i++) {
  64. if (i == 8) {
  65. printf(" :");
  66. }
  67. printf(" ");
  68. }
  69. printf(" ");
  70. for (i = 0; i < numinrow; i++) {
  71. if (isprint(chs[i])) {
  72. printf("%c", chs[i]);
  73. } else {
  74. printf(".");
  75. }
  76. }
  77. }
  78. printf("\n");
  79. }
  80. static int rows_eq(int *a, int *b)
  81. {
  82. int i;
  83. for (i=0; i<16; i++)
  84. if (a[i] != b[i]) {
  85. return 0;
  86. }
  87. return 1;
  88. }
  89. void amqp_dump(void const *buffer, size_t len)
  90. {
  91. unsigned char *buf = (unsigned char *) buffer;
  92. long count = 0;
  93. int numinrow = 0;
  94. int chs[16];
  95. int oldchs[16] = {0};
  96. int showed_dots = 0;
  97. size_t i;
  98. for (i = 0; i < len; i++) {
  99. int ch = buf[i];
  100. if (numinrow == 16) {
  101. int j;
  102. if (rows_eq(oldchs, chs)) {
  103. if (!showed_dots) {
  104. showed_dots = 1;
  105. printf(" .. .. .. .. .. .. .. .. : .. .. .. .. .. .. .. ..\n");
  106. }
  107. } else {
  108. showed_dots = 0;
  109. dump_row(count, numinrow, chs);
  110. }
  111. for (j=0; j<16; j++) {
  112. oldchs[j] = chs[j];
  113. }
  114. numinrow = 0;
  115. }
  116. count++;
  117. chs[numinrow++] = ch;
  118. }
  119. dump_row(count, numinrow, chs);
  120. if (numinrow != 0) {
  121. printf("%08lX:\n", count);
  122. }
  123. }
  124. int main(int argc, char *argv[])
  125. {
  126. QCoreApplication a(argc, argv);
  127. //RabbitMQ start
  128. char const *hostname;
  129. int port, status;
  130. char const *exchange;
  131. char const *bindingkey;
  132. amqp_socket_t *socket = NULL;
  133. amqp_connection_state_t conn;
  134. amqp_bytes_t queuename;
  135. hostname = "localhost";
  136. port = 5672;
  137. exchange = "amq.direct";
  138. bindingkey = "test";
  139. conn = amqp_new_connection();
  140. socket = amqp_tcp_socket_new(conn);
  141. if (!socket) {
  142. qDebug() << "creating TCP socket";
  143. }
  144. status = amqp_socket_open(socket, hostname, port);
  145. if (status) {
  146. qDebug() << "opening TCP socket";
  147. }
  148. die_on_amqp_error(amqp_login(conn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, "guest", "guest"),
  149. "Logging in");
  150. amqp_channel_open(conn, 1);
  151. die_on_amqp_error(amqp_get_rpc_reply(conn), "Opening channel");
  152. //大括号指明变量的作用域
  153. {
  154. amqp_queue_declare_ok_t *r = amqp_queue_declare(conn, 1, amqp_empty_bytes, 0, 0, 0, 1,
  155. amqp_empty_table);
  156. die_on_amqp_error(amqp_get_rpc_reply(conn), "Declaring queue");
  157. queuename = amqp_bytes_malloc_dup(r->queue);
  158. if (queuename.bytes == NULL) {
  159. fprintf(stderr, "Out of memory while copying queue name");
  160. return 1;
  161. }
  162. }
  163. amqp_queue_bind(conn, 1, queuename, amqp_cstring_bytes(exchange), amqp_cstring_bytes(bindingkey),
  164. amqp_empty_table);
  165. die_on_amqp_error(amqp_get_rpc_reply(conn), "Binding queue");
  166. amqp_basic_consume(conn, 1, queuename, amqp_empty_bytes, 0, 1, 0, amqp_empty_table);
  167. die_on_amqp_error(amqp_get_rpc_reply(conn), "Consuming");
  168. {
  169. for (;;) {
  170. amqp_rpc_reply_t res;
  171. amqp_envelope_t envelope;
  172. amqp_maybe_release_buffers(conn);
  173. res = amqp_consume_message(conn, &envelope, NULL, 0);
  174. if (AMQP_RESPONSE_NORMAL != res.reply_type) {
  175. break;
  176. }
  177. printf("Delivery %u, exchange %.*s routingkey %.*s\n",
  178. (unsigned) envelope.delivery_tag,
  179. (int) envelope.exchange.len, (char *) envelope.exchange.bytes,
  180. (int) envelope.routing_key.len, (char *) envelope.routing_key.bytes);
  181. if (envelope.message.properties._flags & AMQP_BASIC_CONTENT_TYPE_FLAG) {
  182. printf("Content-type: %.*s\n",
  183. (int) envelope.message.properties.content_type.len,
  184. (char *) envelope.message.properties.content_type.bytes);
  185. }
  186. printf("----\n");
  187. amqp_dump(envelope.message.body.bytes, envelope.message.body.len);
  188. amqp_destroy_envelope(&envelope);
  189. }
  190. }
  191. die_on_amqp_error(amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS), "Closing channel");
  192. die_on_amqp_error(amqp_connection_close(conn, AMQP_REPLY_SUCCESS), "Closing connection");
  193. die_on_error(amqp_destroy_connection(conn), "Ending connection");
  194. //RabbitMQ end
  195. return a.exec();
  196. }


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/808746
推荐阅读
相关标签
  

闽ICP备14008679号