RabbitMQ-C使用开发详解(Windows环境)

目录

一、概述

二、编译RabbitMQ-c

三、核心原理

3.1生产者与交换机关系

3.2交换机与队列关系

3.3队列与消费者关系

3.4交换机与交换机的关系

四、开发者

4.1接口文件

4.2交换机

声明交换机

删除交换机

向交换机绑定路由键

从交换机解绑路由键

交换机之间绑定路由键

交换机之间解绑路由键

4.3队列

声明队列

清空队列

删除队列

4.4生产者

4.5消费者

4.5.1订阅

4.5.2拉取


RabbitMQ-C使用开发详解(Windows环境)

 

一、概述

讨论的是windows环境下的使用RabbitMQ-c与RabbitMQ服务端的交互。

 

二、编译RabbitMQ-c

RabbitMq的C/C++客户端有很多,我们选用RabbitMq-c。windows环境下的MFC开发,需要把RabbitMq-c客户端编译成dll。

1.下载和安装

下载rabbitmq-c最新代码包:https://github.com/alanxz/rabbitmq-c

下载cmake最新安装包:https://cmake.org/download/

2.使用cmake编译生成适合自己编译环境的工程

第一步:填写源代码路径

第二步:填写建立后的路径,build的文件夹一般建立在源代码路径里,也可以放在其他位置

第三步:点击配置按钮,在配置里面选择属于自己编译环境的名字

第四步:点击生成按钮,不出现运行失败就说明已经编译成功了

       

特别说明:在编译rabbitmq-c是如果出现如图的错误,可以去掉ENABLE_SSL_SUPPORT括号里的对勾。 

 

在以上生成的工程目录下的librabbitmq\Debug路径下会生成librabbitmq.4.lib、librabbitmq.4.dll两个文件,对应的动态库的导出文件在rabbitmq-c-master\librabbitmq目录下。

 

三、核心原理

3.1生产者与交换机关系

生产者与交换机的关系是多对多的有关系,多个生产者可以给同一个交换机生产消息,同时一个生产者也可以能多个交换机生产消息。

 

3.2交换机与队列关系

交换机与队列的关系是多对多的关系,一个交换机可以给多个队列提供消息,同时多个交换机也可以同时给一个队列提供消息。

 

3.3队列与消费者关系

队列与消费者的关系是多对多的关系,一个队列可以同时被多个消费者消费,同时一个消费者可以同时消费多个队列的消息。

3.4交换机与交换机的关系

交换机与交换机的关系,与交换机与队列的关系是一样的。部份交换机充当队列的角色,从其绑定的交换机上分流数据,然后再把自己角色转换成交换机,然后给绑定在自身上的队列分派消息。

所以交换机之间的关系是多对多,一个上级交换机可以绑定多个下级交换机,一个下级交换机可同时绑定多个上级交换机。

四、开发者

4.1接口文件

总共有4个导出文件:

amqp.h:主要的rabbitmq-c客户端接口都在此文件

amqp_tcp_socket.h:与socket相关的接口

mqp_framing.h:不常用的一些接口

amqp_ssl_socket.h:用户ssl方式加密访问rabbitmq-server

 

生产者生产消息过程:

(1)客户端连接到消息队列服务器,打开一个channel。

(2)客户端声明一个exchange,并设置相关属性。

(3)客户端声明一个queue,并设置相关属性。

(4)客户端使用routing key,在exchange和queue之间建立好绑定关系。

(5)客户端投递消息到exchange。

 

RabbitMQ支持消息的持久化:

也就是数据写在磁盘上,为了数据安全考虑,我想大多数用户都会选择持久化。如果exchange和queue都是持久化的,那么它们之间的binding也是持久化的。如果exchange和queue两者之间有一个持久化,一个非持久化,就不允许建立绑定。消息队列持久化包括3个部分:

(1)exchange持久化,在声明时指定durable => 1

(2)queue持久化,在声明时指定durable => 1

(3)消息持久化,在投递时指定delivery_mode=> 2(1是非持久化)

4.2交换机

声明交换机

AMQP_PUBLIC_FUNCTION amqp_exchange_declare_ok_t *AMQP_CALL amqp_exchange_declare(amqp_connection_state_t state, amqp_channel_t channel,amqp_bytes_t exchange, amqp_bytes_t type, amqp_boolean_t passive,amqp_boolean_t durable, amqp_boolean_t auto_delete, amqp_boolean_t internal,amqp_table_t arguments);

 

/**

 * amqp_exchange_declare

 *

 * @param [in] connect连接 amqp_new_connection获取

 * @param [in] channel the channel to do the RPC on,程序自己设置一个通道号,一个连接可以多个通道号。

 * @param [in] exchange 指定交换机名称 eg:amqp_cstring_bytes("exchange_cat")

 * @param [in] type 指定交换机类型,amqp_cstring_bytes("direct") 

 * "fanout" 广播的方式,发送到该exchange的所有队列上。

 * "direct" 通过路由键发送到指定的队列上。

 * "topic" 通过匹配路由键的方式获取,使用通配符*,#

 * @param [in] passive 检测exchange是否存在,设为true,若exchange存在则命令成功返回(调用其他参数不会影响exchange属性),若不存在不会创建exchange,返回错误。设为false,如果exchange不存在则创建exchange,调用成功返回。如果exchange已经存在,并且匹配现在exchange的话则成功返回,如果不匹配则exchange声明失败。

 * @param [in] durable 队列是否持久化

 * @param [in] auto_delete 连接断开的时候,exchange是否自动删除

 * @param [in] internal internal

 * @param [in] arguments arguments

 * @returns amqp_exchange_declare_ok_t

 */

 

Demo示例:


#include <amqp.h>
#include <amqp_tcp_socket.h>
void die_on_amqp_error2(amqp_rpc_reply_t x, char const *context) {
	char sLog[1024] = {0};
	switch (x.reply_type) {
	case AMQP_RESPONSE_NORMAL:
		return;

	case AMQP_RESPONSE_NONE:
		printf(sLog, "%s: missing RPC reply type!\n", context);
		break;

	case AMQP_RESPONSE_LIBRARY_EXCEPTION:
		printf(sLog, "%s: %s\n", context, amqp_error_string2(x.library_error));
		break;

	case AMQP_RESPONSE_SERVER_EXCEPTION:
		switch (x.reply.id) {
		case AMQP_CONNECTION_CLOSE_METHOD: {
			amqp_connection_close_t *m =
				(amqp_connection_close_t *)x.reply.decoded;
			printf(sLog, "%s: server connection error %uh, message: %.*s\n",
				context, m->reply_code, (int)m->reply_text.len,
				(char *)m->reply_text.bytes);
			break;
										   }
		case AMQP_CHANNEL_CLOSE_METHOD: {
			amqp_channel_close_t *m = (amqp_channel_close_t *)x.reply.decoded;
			printf(sLog, "%s: server channel error %uh, message: %.*s\n",
				context, m->reply_code, (int)m->reply_text.len,
				(char *)m->reply_text.bytes);
			break;
										}
		default:
			printf(sLog, "%s: unknown server error, method id 0x%08X\n",
				context, x.reply.id);
			break;
		}
		break;
	}

	AfxMessageBox(sLog);
}


void die_on_error2(int x, char const *context) {
	if (x < 0) {
		char sLog[1024] = {0};
		printf(sLog, "%s: %s\n", context, amqp_error_string2(x));
		AfxMessageBox(sLog);
  • 8
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MingoJ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值