概述

最近项目消息队列服务选用了rabbitmq,server端用的C++开发的,于是需要开发rabbitmq的c++客户端,国际惯例先百度了一圈,然后github搜了一圈,竟然发现排名靠前的需要付费才能使用,尼玛这都拿出来骗钱(愤青了),于是产生了写个客户端给大家使用的念头。

我的应用场景是这样的生产者是用java写的(java别说了,一搜一大堆,改个服务器地址就能用),服务端作为消费者,老本行用的C++开发的,只需写个c++的rabbitmq客户端嵌入到我的server里就行,所有的消费者监听的一个队列,无需指定routing key和exchange,任何一个消费者消费到数据就行(我的服务端是个集群)。话不多说上代码。

实现

我的环境是Linux centos7.2

amqpclient.cpp源码如下:

  1. #include <unistd.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdint.h>
  6. #include "amqp_tcp_socket.h"
  7. #include "amqp.h"
  8. #include "amqp_framing.h"
  9. #include "utils.h"
  10. #include "platform_utils.h"
  11. #include "amqpclient.h"
  12. /*
  13. * 构造函数
  14. * hostname,port,user,pwd,vhost
  15. */
  16. AmqpClient::AmqpClient(const char* hostname, const int port, const char* user,
  17. const char* pwd, const char* vhost, const char* queuename)
  18. {
  19. if((hostname != NULL) || (port != 0) || (user != NULL)
  20. || (pwd != NULL) || (vhost != NULL) || (queuename != NULL))
  21. {
  22. strcpy(this->m_hostname, hostname);
  23. this->m_port = port;
  24. strcpy(this->m_user, user);
  25. strcpy(this->m_pwd, pwd);
  26. strcpy(this->m_vhost, vhost);
  27. strcpy(this->m_queuename, queuename);
  28. }
  29. }
  30. bool AmqpClient::ConnectRabbitmq()
  31. {
  32. amqp_socket_t *socket ;
  33. amqp_rpc_reply_t reply ;
  34. int status;
  35. conn = amqp_new_connection();
  36. socket = amqp_tcp_socket_new(conn);
  37. if(!socket)
  38. {
  39. printf("amqp new socket error\n");
  40. return 0;
  41. }
  42. status = amqp_socket_open(socket, m_hostname, m_port);
  43. if(status)
  44. {
  45. printf("amqp open socket error\n");
  46. return 0;
  47. }
  48. reply = amqp_login(conn, m_vhost, 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, m_user, m_pwd);
  49. if (reply.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION)
  50. {
  51. printf("amqp login error\n");
  52. return 0;
  53. }
  54. amqp_channel_open(conn, 1);
  55. reply = amqp_get_rpc_reply(conn);
  56. if(reply.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION)
  57. {
  58. printf("ConnectRabbitmq::amqp get rpc_reply error\n");
  59. return 0;
  60. }
  61. }
  62. bool AmqpClient::StartConsumer()
  63. {
  64. amqp_rpc_reply_t reply ;
  65. //自动回复ACK
  66. amqp_basic_consume(conn, 1, amqp_cstring_bytes(m_queuename), amqp_empty_bytes, 0, 1, 0, amqp_empty_table);
  67. reply = amqp_get_rpc_reply(conn);
  68. if(reply.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION)
  69. {
  70. printf("StartConsumer::amqp get rpc_reply error\n");
  71. return false;
  72. }
  73. {
  74. for (;;)
  75. {
  76. amqp_rpc_reply_t res;
  77. amqp_envelope_t envelope;
  78. amqp_maybe_release_buffers(conn);
  79. res = amqp_consume_message(conn, &envelope, NULL, 0);
  80. if (AMQP_RESPONSE_NORMAL != res.reply_type) {
  81. break;
  82. }
  83. printf("Delivery %u, exchange %.*s routingkey %.*s\n",
  84. (unsigned) envelope.delivery_tag,
  85. (int) envelope.exchange.len, (char *) envelope.exchange.bytes,
  86. (int) envelope.routing_key.len, (char *) envelope.routing_key.bytes);
  87. if (envelope.message.properties._flags & AMQP_BASIC_CONTENT_TYPE_FLAG) {
  88. printf("Content-type: %.*s\n",
  89. (int) envelope.message.properties.content_type.len,
  90. (char *) envelope.message.properties.content_type.bytes);
  91. }
  92. printf("----\n");
  93. amqp_dump(envelope.message.body.bytes, envelope.message.body.len);
  94. amqp_destroy_envelope(&envelope);
  95. }
  96. }
  97. }
  98. void AmqpClient::CloseConnect()
  99. {
  100. amqp_rpc_reply_t reply ;
  101. amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS);
  102. amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
  103. amqp_destroy_connection(conn);
  104. }

amqpclient.h源码如下:

  1. #ifndef _AMQPCLIENT_H
  2. #define _AMQPCLIENT_H
  3. #include "amqp.h"
  4. class AmqpClient
  5. {
  6. public:
  7. AmqpClient(const char* hostname, const int port, const char* user, const char* pwd,
  8. const char* vhost, const char* queuename);
  9. bool ConnectRabbitmq();
  10. bool StartConsumer();
  11. void CloseConnect();
  12. private:
  13. amqp_connection_state_t conn = NULL;
  14. char m_hostname[128];
  15. int m_port;
  16. char m_user[128];
  17. char m_pwd[128];
  18. char m_vhost[128];
  19. char m_queuename[128];
  20. };
  21. #endif

main.cpp源码如下:

  1. #include <stdio.h>
  2. #include "amqpclient.h"
  3. int main()
  4. {
  5. const char* hostname = "192.168.12.20";
  6. const int port = 5672;
  7. const char* user = "woniu201";
  8. const char* pwd = "woniu201";
  9. const char* vhost = "/";
  10. const char* queuename = "queuename001";
  11. AmqpClient amqpClient(hostname, port, user, pwd, vhost, queuename);
  12. amqpClient.ConnectRabbitmq();
  13. printf("connect rabbitmq succ, is consuming!\n");
  14. amqpClient.StartConsumer();
  15. return 1;
  16. }

Makefile文件:

  1. EXE=rabbitmq_consumer
  2. SUBDIR=src
  3. #CXXFLAGS:编译选项, LDFLAGS:链接选项
  4. CXXFLAGS +=
  5. LDFLAGS += -L/usr/local/lib -lrabbitmq
  6. CXX_SOURCES =$(foreach dir,$(SUBDIR), $(wildcard $(dir)/*.cpp))
  7. CXX_OBJECTS=$(patsubst %.cpp, %.o, $(CXX_SOURCES))
  8. DEP_FILES =$(patsubst %.o, %.d, $(CXX_OBJECTS))
  9. $(EXE): $(CXX_OBJECTS)
  10. g++ $(CXX_OBJECTS) -o $(EXE) $(LDFLAGS)
  11. %.o: %.cpp
  12. g++ -c $(CXXFLAGS) -MMD $< -o $@
  13. -include $(DEP_FILES)
  14. clean:
  15. rm -rf $(CXX_OBJECTS) $(DEP_FILES) $(EXE)
  16. test:
  17. echo $(CXX_OBJECTS)
  18. initlib:
  19. ln -s lib/librabbitmq.so.4.2.0 /usr/local/lib/librabbitmq.so
  20. ln -s lib/librabbitmq.so.4.2.0 /usr/lib64/librabbitmq.so.4

这里用到了librabbitmq.so.4动态库,make前先执行make initlib指令,会把所用的librabbitmq.so库放到系统环境中。

make完后会生产rabbitmq_consumer可执行文件,./rabbitmq_consumer执行。

测试结果如下:

如果到这里还有问题可以直接下载我的源码或者留言交流:http://download.csdn.net/detail/woniu211111/9911075

没有下载积分的,可以关注下面公众号,回复"107"获取源码

欢迎加群交流:C/C++开发交流

Rabbitmq C++客户端 Rabbitmq Client的更多相关文章

  1. RabbitMQ C#客户端自动重连

    重要参考文章来源:http://gigi.nullneuron.net/gigilabs/resilient-connections-with-rabbitmq-net-client/ 参考代码:ht ...

  2. C#基于RabbitMQ实现客户端之间消息通讯实战演练

    一.背景介绍和描述 MQ消息队列已经逐渐成为企业IT系统内部通信的核心手段.它具有低耦合.可靠投递.广播.流量控制.最终一致性等一系列功能,成为异步RPC的主要手段之一.何时需要消息队列?当你需要使用 ...

  3. RabbitMQ JAVA客户端调用例子

    1.安装erlang 下载地址:http://www.erlang.org/downloads 设置ERLANG环境变量 2.安装RabbitMQ 下载地址: http://www.rabbitmq. ...

  4. RabbitMQ GUI客户端工具(RabbitMQ Assistant)

    RabbitMQ GUI客户端工具(RabbitMQ Assistant) 平时用控制台或者网页进行管理不免有点不方便,尤其在读取消息的时候不支持过滤和批量发送消息,在此推荐一个漂亮的GUI客户端工具 ...

  5. RabbitMQ交换机、RabbitMQ整合springCloud

    目标 1.交换机 2.RabbitMQ整合springCloud 交换机 蓝色区域===生产者 红色区域===Server:又称Broker,接受客户端的连接,实现AMQP实体服务 绿色区域===消费 ...

  6. .Net RabbitMQ实战指南——RabbitMQ相关概念介绍

    什么是消息中间件 消息(Message)是指在应用间传送的数据.消息可以非常简单,比如只包含文本字符串.JSON等,也可以很复杂,比如内嵌对象. 消息队列中间件(Message Queue Middl ...

  7. RabbitMQ入门到进阶(Spring整合RabbitMQ&SpringBoot整合RabbitMQ)

    1.MQ简介 MQ 全称为 Message Queue,是在消息的传输过程中保存消息的容器.多用于分布式系统 之间进行通信. 2.为什么要用 MQ 1.流量消峰 没使用MQ 使用了MQ 2.应用解耦 ...

  8. .NET文件并发与RabbitMQ(初探RabbitMQ)

    本文版权归博客园和作者吴双本人共同所有.欢迎转载,转载和爬虫请注明原文地址:http://www.cnblogs.com/tdws/p/5860668.html 想必MQ这两个字母对于各位前辈们和老司 ...

  9. 基于 IdentityServer3 实现 OAuth 2.0 授权服务【客户端模式(Client Credentials Grant)】

    github:https://github.com/IdentityServer/IdentityServer3/ documentation:https://identityserver.githu ...

随机推荐

  1. 通过Confulence API统计用户文档贡献量

    Confulence提供了非常清晰的RESTful API,直接使用API比confluence_python_cli这个库更方便. 参考文档:https://developer.atlassian. ...

  2. [Go] 基础系列一: for-select中的break、continue和return

    break select中的break,类似c系列中的break,break后的语句不执行 for和select一同使用,有坑 break只能跳出select,无法跳出for package test ...

  3. JavaBean转Map

    1.需要的jar包 <dependency> <groupId>com.google.guava</groupId> <artifactId>guava ...

  4. Hadoop hadoop(2.9.0)---uber模式(小作业“ubertask”优化)

    前言: 在有些情况下,运行于Hadoop集群上的一些mapreduce作业本身的数据量并不是很大,如果此时的任务分片很多,那么为每个map任务或者reduce任务频繁创建Container,势必会增加 ...

  5. dubbo zookeeper图解入门配置

    这次主要是对dubbo 和zookeeper的配置做个记录,以便以后自己忘记了,或者踩的坑再次被踩 快速阅读 zookeerer类似 springcloud中的Eureka都做为注册中心,用srpin ...

  6. thymeleaf 声明

    <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd&qu ...

  7. WebSocketSharp中WebSocket类

    websocket-sharp.clone, Version=1.0.2.39869 WebSocket由方法调用事件改为实例化委托调用,两种构造 1.构造函数 第一种 // // 摘要: // In ...

  8. CSS中的cursor属性

    css中的cursor这个属性是用来设置光标形状的. 这个属性定义了鼠标指针放在一个元素边界范围内时所用的光标的形状. 默认值:auto 继承性:yes 出现版本:css2 JavaScript语法: ...

  9. PyMouse、PyKeyboard用python操作鼠标和键盘

    1.PyUserInput 简介 PyUserInput是一个使用python的跨平台的操作鼠标和键盘的模块,非常方便使用.支持的平台及依赖如下: Linux - Xlib Mac - Quartz, ...

  10. JQuery.BlockUI使用方法举例

    JQuery.BlockUI是众多JQuery插件弹出层中的一个,它小巧(原版16k,压缩后10左右),容易使用, 功能齐全,支持Iframe,支持Modal,可定制性高也意味他默认谦虚的外表. jQ ...