RabbitMQ是建立在AMQP(Advanced Message Queuing Protocol,高级消息队列协议)基础上的,而AMQP是建立在TCP协议之上的。

因此,RabbitMQ是需要建立TCP连接的。其建立连接的方法如下:

//首选创建一个连接工厂对象
var factory = new ConnectionFactory() { HostName = "localhost", UserName = "yyt", Password = "yyt888888",VirtualHost="log" };
//然后使用工厂对象创建一个TCP连接
using (var connection = factory.CreateConnection()){ }

TCP连接的频繁创建与销毁是需要很大开销的,因此RabbitMQ需要在当前TCP连接上建立一些虚拟管道用作通信,就如同一根电缆,外部那根大的橡胶线圈就如同在TCP上建立的连接,内部每一根铜线就如同每一个通信的虚拟管道。如果有多个通信,可以建立多个虚拟管道。创建一根虚拟管道的方法如下:

//在当前连接上创建一根通信的虚拟管道
using (var channel = connection.CreateModel()) {
//TO-DO:do something
}

现在通信的管道有了,接下来就开始发送消息。在发送消息之前,需要创建交换机和队列。因为可以通过交换机去找到队列,从而可以将消息存放到队列中,所以发送消息之前,必须先创建交换机和队列,除非该交换机和队列已经存在。

创建交换机的方法如下:

channel.ExchangeDeclare("e.log",  //交换机名称
"direct"); //交换机类型

创建队列的方法如下:

channel.QueueDeclare(queue: "q.log.info", //队列名称
durable: false, //当前队列是否持久化
exclusive: false, //是否是私有队列
autoDelete: false, //该队列在最后一个consumer断开之后是否自动删除
arguments: null); //其他配置参数

交换机怎么知道将消息放入哪个队列呢?因此需要将交换机和队列进行绑定,并产生一个RoutingKey,以后该交换机就可以通过这个RoutingKey找到对应的队列了。

将交换机和队列绑定的方法如下:

channel.QueueBind("q.log.info", //队列名称
"e.log", //交换机名称
"log.info"); //自定义的RoutingKey

重点来啦!前面所做的一切就是为了下面这句代码,发送消息到RabbitMQ的队列中。请记住:RabbitMQ的队列中存储的是二进制数据。

发送消息的方法如下:

//生成二进制消息
var body = Encoding.UTF8.GetBytes("hello world!");
//将二进制消息通过交换机发送到队列中
channel.BasicPublish(exchange: "e.log", //交换机
routingKey: "log.info", //RoutingKey
basicProperties: null, //先让它为空
body: body); //发送的消息(二进制数据)

至此,一个简单的消息发送操作就完成了。

接下来开始接收消息操作的演示。

接收端在接收消息之前,也需要连接RabbitMQ服务器和创建通信管道。

但是有一个问题,如果该消息队列不存在,还能正常接收消息吗?答案是肯定不能的,而且还会报错!

因此,我们在接收消息前,还得声明一个队列。如果该队列存在,就返回该队列,如果该队列不存在,就创建一个队列。

对于同一个队列,接收端创建的方式必须要和发送端一样,每个参数都要一样。RabbitMQ不允许使用不同的参数声明同一个队列,否则会报错!

接收端连接RabbitMQ服务器、创建通信管道和创建队列方式与发送端一样,如下方法:

//首选创建一个连接工厂对象
var factory = new ConnectionFactory() { HostName = "localhost", UserName = "yyt", Password = "yyt888888",VirtualHost="log" };
//然后使用工厂对象创建一个TCP连接
using (var connection = factory.CreateConnection()){
//在当前连接上创建一根通信的虚拟管道
using (var channel = connection.CreateModel()) {
channel.QueueDeclare(queue: "q.log.info", //队列名称
durable: false, //当前队列是否持久化
exclusive: false, //是否是私有队列
autoDelete: false, //该队列在最后一个consumer断开之后是否自动删除
arguments: null); //其他配置参数 }
}

接下来创建一个消费者,用来接收并处理从队列中获取的消息。

创建消费者的方法如下:

//新建一个事件驱动的消费者
var consumer = new EventingBasicConsumer(channel);
//消费者收到消息后的事件处理
consumer.Received += (model, ea) => {
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
Console.WriteLine(" [x] Received {0}", message);
};
//通知RabbitMQ服务器,我要接收q.log.info队列的消息,快点发消息给我
channel.BasicConsume(queue: "q.log.info",
noAck: true,
consumer: consumer);

至此,发送消息与接收消息就演示完毕。

我们整合一下整个代码,如下所示:

消息发送端(生产者):

//首先创建一个连接工厂对象
var factory = new ConnectionFactory() { HostName = "localhost", UserName = "yyt", Password = "yyt888888",VirtualHost="log" };
//然后使用工厂对象创建一个TCP连接
using (var connection = factory.CreateConnection()){
//在当前连接上创建一根通信的虚拟管道
using (var channel = connection.CreateModel()) {
//声明一个交换机
channel.ExchangeDeclare("e.log", //交换机名称
     "direct"); //交换机类型
//声明一个队列
channel.QueueDeclare(queue: "q.log.info", //队列名称
durable: false, //当前队列是否持久化
exclusive: false, //是否是私有队列
autoDelete: false, //该队列在最后一个consumer断开之后是否自动删除
arguments: null); //其他配置参数
//将该队列绑定到交换机,并设置RoutingKey=log.info,以便交换机能通过RoutingKey找到该队列
channel.QueueBind("q.log.info", //队列名称
"e.log", //交换机名称
"log.info"); //自定义的RoutingKey //生成二进制消息
var body = Encoding.UTF8.GetBytes("hello world!");
//将二进制消息通过交换机发送到队列中
channel.BasicPublish(exchange: "e.log", //交换机
routingKey: "log.info", //RoutingKey
basicProperties: null, //先让它为空
body: body); //发送的消息(二进制数据) }
}

消息接收端(消费者):

//首选创建一个连接工厂对象
var factory = new ConnectionFactory() { HostName = "localhost", UserName = "yyt", Password = "yyt888888",VirtualHost="log" };
//然后使用工厂对象创建一个TCP连接
using (var connection = factory.CreateConnection()){
//在当前连接上创建一根通信的虚拟管道
using (var channel = connection.CreateModel()) {
channel.QueueDeclare(queue: "q.log.info", //队列名称
durable: false, //当前队列是否持久化
exclusive: false, //是否是私有队列
autoDelete: false, //该队列在最后一个consumer断开之后是否自动删除
arguments: null); //其他配置参数 //新建一个事件驱动的消费者
var consumer = new EventingBasicConsumer(channel);
//消费者收到消息后的事件处理
consumer.Received += (model, ea) => {
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
Console.WriteLine(" [x] Received {0}", message);
};
//通知RabbitMQ服务器,我要接收q.log.info队列的消息,快点发消息给我
channel.BasicConsume(queue: "q.log.info",
noAck: true,
consumer: consumer); }
}

以上就是一个关于RabbitMQ消息队列的简单的消息发送和接收过程。

最后让我们喊出我们的口号:捉住那只兔子,炖了它!

RabbitMQ 简单的消息发送与接收的更多相关文章

  1. C#TCPClient应用-一个简单的消息发送和接收

    TcpSend窗口用于发送消息,另外写一个用于接收消息的应用程序,消息接受到以后,必须要关闭接收消息的窗口,才能在接收新的消息,不知道怎么能解决这个问题. 源代码: 发送消息的窗口代码 using S ...

  2. 整合Spring Cloud Stream Binder与GCP Pubsub进行消息发送与接收

    我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 前言 之前的文章<整合Spring Cloud Stream Binder与RabbitMQ进行消息发送与接收& ...

  3. 基于springboot工程浅谈整合rabbitmq怎么样防止消息发送mq不丢失和消费mq的消息防止丢失

    本文只针对springboot整合rabbitmq的消息防丢失,话不多说,上干货.... 设置发送mq消息不丢失实现思路 执行的方案: 第一步,要对队列,消息以及交换机进行持久化操作(保存到物理磁盘中 ...

  4. C#的Socket简单实现消息发送

    Socket一般用于网络之间的通信,在这里,实现的是服务端与客户端的简单消息通信.首先是客户端的搭建,一般步骤是先建立Socket绑定本地的IP和端口,并对远端连接进行连接进行监听,这里的监听一般开启 ...

  5. DICOM医学图像处理:DIMSE消息发送与接收“大同小异”之DCMTK fo-dicom mDCM

    背景: 从DICOM网络传输一文开始,相继介绍了C-ECHO.C-FIND.C-STORE.C-MOVE等DIMSE-C服务的简单实现,博文中的代码给出的实例都是基于fo-dicom库来实现的,原因只 ...

  6. SpringBoot整合RabbitMQ,实现消息发送和消费以及多个消费者的情况

    下载安装Erlang和RabbitMQ Erlang和RabbitMQ:https://www.cnblogs.com/theRhyme/p/10069611.html AMQP协议 https:// ...

  7. TeamTalk Android代码分析(业务流程篇)---消息发送和接收的整体逻辑说明

    第一次纪录东西,也没有特别的顺序,想到哪里就随手画了一下,后续会继续整理- 6.2消息页面动作流程 6.2.1 消息页面初始化的总体思路 1.页面数据的填充更新直接由页面主线程从本地数据库请求 2.数 ...

  8. java操作rabbitmq实现简单的消息发送(socket编程的升级)

    准备: 1.下载rabbitmq并搭建环境(和python那篇一样:http://www.cnblogs.com/g177w/p/8176797.html) 2.下载支持的jar包(http://re ...

  9. 整合Spring Cloud Stream Binder与RabbitMQ进行消息发送与接收

    我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 前言 Spring Cloud Stream专门用于事件驱动的微服务系统,使用消息中间件来收发信息.使用Spring ...

随机推荐

  1. python+selenium2(二)

    看完第一个程序,可能有不懂得地方,里面有定位元素的方式,之后会具体介绍定位的方式.这一篇介绍下对浏览器的操作. (1)浏览器的最大化   有点问题, Message: unknown error: c ...

  2. python中的面向对象学习以及类的封装(这篇文章初学者一定要好好看)

    这篇文章对于初学者可以很有效的理解面对过程.面对对象 一.首先介绍一下面向过程和面向对象的比较: 面向过程 VS 面向对象 编程范式 编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何 ...

  3. 用R的igraph包来画蛋白质互作网络图 | PPI | protein protein interaction network | Cytoscape

    igraph语法简单,画图快速. Cytoscape专业,个性定制. 最终效果图: 当然也可以用Cytoscape来画. 参考:Network visualization with R Cytosca ...

  4. zookeeper在搭建的时候,解决后台启动为standalone模式问题

    今天在搭建zookeeper,搭建完成之后,启动一直报错: 上网查了好多资料:有几种解决方案: 1.在配置文件conf目录下,将zoo_sample.cfg删除,只留zoo.cfg(然而就我的情况而言 ...

  5. 基于AngularJS的Onsen UI --Onsen UI学习笔记

    AngularJS与Onsen UI的结合,Onsen UI应用程序实际上是一个AngularJS 1应用程序. <!doctype html><html lang="en ...

  6. hihocoder-1419 后缀数组四·重复旋律4 求连续重复次数最多的子串

    对于重复次数,如果确定了重复子串的长度len,那重复次数k=lcp(start,start+len)/len+1.而暴力枚举start和len的复杂度是O(n^2),不能接受.而有一个规律,若我们只枚 ...

  7. 正睿 2018 提高组十连测 Day2 T2 B

    题目链接 http://www.zhengruioi.com/contest/84/problem/318 题解写的比较清楚,直接扒过来了. B 算法 1 直接按题意枚举,动态规划或是记忆化搜索. 时 ...

  8. Subordinates CodeForces - 737C (树,构造)

    大意: 求构造一棵树, 每个节点回答它的祖先个数, 求最少打错次数. 挺简单的一个构造, 祖先个数等价于节点深度, 所以只需要确定一个最大深度然后贪心即可. 需要特判一下根的深度, 再特判一下只有一个 ...

  9. Selenium-WebDriver驱动对照表

    Chrome 对于chrome浏览器,有时候会有闪退的情况,也许是版本冲突的问题,我们要对照着这个表来对照查看是不是webdriver和chrome版本不对 chromedriver版本 支持的Chr ...

  10. 【PowerDesigner】【1】简单介绍

    正文: 创建表格 File→New Model→(Model types; Physical Data Model; Physical Diagram)Model name:名称:DBMS:数据库类型 ...