转:https://www.cnblogs.com/80X86/p/5557801.html

功能需求,用到了队列,用的时候出了很多问题,现在总结一下,希望能对有需要的人提供帮助。

我的需求很简单,就是多个客户端连接到我的一个小型的数据转发服务器上,开始使用的是Socket通信实现这个功能,一旦数据服务器接收到来自不同客户端发来的消息,就对这些消息进行处理(我这里是将数据接收到后再转发到另一个服务器上),但考虑到客户端是每隔一个很短的时间周期向服务器发送信息,并且连接客服端数量比较多的时候,担心会产生并发访问的问题,也希望避免 数据转发服务器 频繁地从多个不同线程获取信息而出现其他未知问题,所以在处理客户端向数据转发服务器发送信息的时候采取队列的方式。

一般情况下,使用MSMQ,要先安装消息服务,这个直接百度就行;

在VS里添加 Messaging引用,就可以使用MessageQueue这个类了;接下来就要思考清楚你的数据(消息)的流向问题,之前因为自己对队列的错误认识,对到底在哪创建队列,队列的消息又由谁去发送和接收没有弄清除,还有参考的一些写得不是太清晰地博文,绕了好大一圈,所以今天在这里以我自己的项目需求为例子,说明 1、如何创建队列 2、如何向队列发送消息 3、 如何获取队列中的消息

首先、创建队列:根据我的需求,我要通过Socket通信将信息发送至数据转发服务器,因此为了避免并发访问问题的产生,消息队列应当建立在数据转发服务器上;

MessageQueue myqueue = null;
       string queuepath = @".\private$\queuedemo"; if (!MessageQueue.Exists(queuepath))
{
myqueue = MessageQueue.Create(queuepath);
}
myqueue = new MessageQueue(queuepath);

这样就在数据转发服务器端创建了一个名为queuedemo的消息队列;从客户端要发送的消息就保存在这个队列里,你可以通过计算机管理->服务和应用下的消息队列中看到你创建的queuedemo队列,private$关键字是说明队列为专用队列,如果没有这个关键字还要配置域服务器,还是挺麻烦,这个还是借助百度吧,前面的“.”代表创建的队列目录是本机,这个队列一旦创建成功,就是系统的事了,接下来要做的就是你怎么去把消息写进这个队列,或者读取队列的值 这里要特别注意不要将queuepath路径字符串写成

string queuepath = @"FormatName:Direct=TCP:192.168.1.153\private$\queuedemo";

这样写的话是用于远程计算机对这个队列进行访问的,因为MessageQueue的Create()和Exisit()方法是没办法去识别上述FormatName格式的,还有要确保Create()函数要被执行了之后再用MessageQueue实例去引用;这样服务器端队列的创建就完成了;

在客户端中,向队列发送信息;

string s = "客户端往队列里发送的信息");
System.Messaging.Message msg = new System.Messaging.Message();
msg.Body = s;
msg.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); MessageQueue mq = new MessageQueue(@"FormatName:Direct=TCP:192.168.1.153\private$\queuedemo");
mq.Send(msg);

在客户端中,用一个MessageQueue实例指向服务器本机上创建的队列路径,这时,MessageQueue实例的构造函数里的路径就一定要用FormatName格式,指明是TCP通信还是HTTP还是Machine如我上面代码所示,然后调用Send()方法,将消息写进队列,这个要求发送的对象要以序列化的方式写进去,所以要设置formatter,这里用的是XmlMessageFormatter 还有BinaryMessageFormatter等等 注意保存你消息的 消息体Body是Object类型的 因此可以将你写的任何一个类的对象发送至消息队列

在服务器中接收消息队列

MessageQueue mq = new MessageQueue(@".\private$\queuedemo");

            mq.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });
Thread th = new Thread(() =>
{
while (true)
{
System.Messaging.Message msg = mq.Receive();
if (msg != null)
{
MessageBox.Show(msg.Body.ToString());
} }
});
th.IsBackground = true;
th.Start();

在本机上可以新创建一个队列实例指向本机的队列,然后按照之前约定的序列化格式反序列化消息体所以将新的队列实例的foarmatter属性赋值为发送时的formatter属性如代码所示,这个时候就直接用Receive()得到消息体,然后对消息体里的信息做处理,我这里是开启一个线程显示队列的消息,只要有新的消息写入,我就在消息框中输出

这个时候可能客户端无法向远程服务器成功发送消息,原因基本权限问题 服务器的消息队列的权限没有对未验证的客户端开放  你要在服务器队列里分配对应权限 如果你想读取队列的内容 还需要加系统变量

问题解决办法

1. 服务器端

服务器上消息队列权限设置:给ANONYMOUS LOGON赋予所有权限;

修改服务器的注册表,允许非验证客户端访问

  • 注册表新增HKLM\Software\Microsoft\MSMQ\Parameters\security\AllowNonauthenticatedRpc项,设置其DWORD值为1
  • 注册表新增HKLM\Software\Microsoft\MSMQ\Parameters\security\NewRemoteReadServerDenyWorkgroupClient项,设置其DWORD值为1

MSMQ的安全访问控制说明参见:http://msdn.microsoft.com/en-us/library/4108f68e-80f5-40e1-b3df-b713cc4dff79(prot.20).aspx

这样客户端就可以读取服务器里的队列信息了 当然一般业务逻辑上不这么做 因为他只负责发送消息 ,综上,就是使用消息队列 跨服务器读写的 最基本的用法

http://www.cnblogs.com/itjeff/p/6026798.html

 static void msgQueue()
{
System.Messaging.Message msg = null; //对列发送或读取的实际消息或数据
MessageQueue mq = null; //接收/发送消息的MSMQ消息队列 try
{
msg = new Message();
msg.Priority = MessagePriority.Normal;//普通消息的优先级
if (!MessageQueue.Exists(@".\Private$\TechRepublic"))
{
mq = MessageQueue.Create(@".\Private$\TechRepublic");
} //如果不存在则创建它
else
{
mq = new MessageQueue(@".\Private$\TechRepublic");
}
msg.Label = "Test Message";
msg.Body = "this is only a test 01";
mq.Send(msg);
Console.WriteLine("message sent"); }
catch (System.Messaging.MessageQueueException ex)
{ Console.WriteLine("MSMQ Error:" + ex.ToString());
}
catch (Exception ex)
{ Console.WriteLine("error:" + ex.ToString()); }
finally
{
mq.Close();
}
}

send

远程:string queuepath = @"FormatName:Direct=TCP:192.168.1.153\private$\queuedemo";

static void msgReceive()
{
Message msg = null;
MessageQueue mq = null;
try
{
mq = new MessageQueue(@".\Private$\TechRepublic");
msg = mq.Receive(new TimeSpan(, , ));//timespan对象指定异常出现时系统的等待时间。
msg.Formatter = new XmlMessageFormatter(new string[] { "System.String,mscorlib" }); //对象被转换成字符串读取前面存储的文本
mq.Receive(); //从队列中读取消息,它的值显示在控制台中
Console.WriteLine(msg.Label.ToString() + "__" + msg.Body.ToString()); }
catch (System.Messaging.MessageQueueException ex)
{ Console.WriteLine("MSMQ Error" + ex.ToString());
}
catch (Exception ex)
{ Console.WriteLine("Error:" + ex.ToString());
}
finally
{ mq.Close(); }
}

Receive

C# 使用消息队列,包括远程访问的更多相关文章

  1. RabbitMQ,Apache的ActiveMQ,阿里RocketMQ,Kafka,ZeroMQ,MetaMQ,Redis也可实现消息队列,RabbitMQ的应用场景以及基本原理介绍,RabbitMQ基础知识详解,RabbitMQ布曙

    消息队列及常见消息队列介绍 2017-10-10 09:35操作系统/客户端/人脸识别 一.消息队列(MQ)概述 消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以 ...

  2. 消息队列 ActiveMQ 、RocketMQ 、RabbitMQ 和 Kafka 如何选择?

    「 预计阅读 6 分钟 」 旁白:这是一篇拖更了N久的文章...0.0(看不见我~) 往期回顾 前端框架 jQuery 和 Vue 如何选择? 安全框架 Shiro 和 Spring Security ...

  3. Handler机制中的消息队列

    --> 学习自蘑菇街大佬 Handler机制可以看成是一个消息阻塞队列,当有消息时立即处理消息,没有消息时则阻塞.在Android系统中APP启动后很快进入死循环,不断读取MessageQueu ...

  4. 【转】C# 使用消息队列,包括远程访问

    出处:http://www.cnblogs.com/80X86/p/5557801.html 近期做一个小的功能需求,用到了队列,用的时候出了很多问题,现在总结一下,希望能对有需要的人提供帮助. 我的 ...

  5. MSMQ消息队列,包括远程访问

    之前的项目用到了队列,现在总结一下,下面有非常详细的DEMO,希望能对有需要的人提供帮助. 使用场景:在项目中,将一些无需即时返回且耗时的操作提取出来,进行了异步处理,而这种异步处理的方式大大的节省了 ...

  6. Python并发编程-RabbitMQ消息队列

    RabbitMQ队列 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Queue, 消息队列 ...

  7. (十)RabbitMQ消息队列-高可用集群部署实战

    原文:(十)RabbitMQ消息队列-高可用集群部署实战 前几章讲到RabbitMQ单主机模式的搭建和使用,我们在实际生产环境中出于对性能还有可用性的考虑会采用集群的模式来部署RabbitMQ. Ra ...

  8. C# 消息队列之 RabbitMQ 基础入门

    Ø  简介 C# 实现消息队列的方式有很多种,比如:MSMQ.RabbitMQ.EQueue 等,本文主要介绍使用 RabbitMQ 实现消息队列的基础入门.包括如下内容: 1.   什么是消息队列? ...

  9. 消息队列 Kafka 的基本知识及 .NET Core 客户端

    前言 最新项目中要用到消息队列来做消息的传输,之所以选着 Kafka 是因为要配合其他 java 项目中,所以就对 Kafka 了解了一下,也算是做个笔记吧. 本篇不谈论 Kafka 和其他的一些消息 ...

随机推荐

  1. GPU,CUDA,cuDNN的理解

    最近用到这方面的知识,感觉这篇文章写的很好,为了方便自己查阅,就搬运了过来,如果牵涉到侵权,请联系我,我会删除该博文!!! 我们知道做深度学习离不开GPU,不过一直以来对GPU和CPU的差别,CUDA ...

  2. 对接极光IM之修改头像

    因为项目中使用了极光IM,在对接极光的时候,发现了如果想要在改变自己个人中心的头像同时改变极光IM的头像,就必须要将本地磁盘的文件上传到极光服务器,根据反馈的media_id来进行修改头像. 但是因为 ...

  3. 编译安装log4cxx

    1.介绍 Log4cxx是开放源代码项目Apache Logging Service的子项目之一,是Java社区著名的log4j的c++移植版,用于为C++程序提供日志功能,以便开发者对目标程序进行调 ...

  4. Error: connection reset by peer ,during filebeat connect to elk.

    Error screenshot like below: Reason: What I found that was the machine failing had same configuratio ...

  5. jpa batch批量操作save和persist比较

    1.网上最常见的JPA----entityManager批量操作方法 private EntityManager em; @PersistenceContext(name = "Entity ...

  6. 最短路【洛谷P1841】 [JSOI2007]重要的城市

    P1841 [JSOI2007]重要的城市 题目描述 参加jsoi冬令营的同学最近发现,由于南航校内修路截断了原来通向计算中心的路,导致去的路程比原先增加了近一公里.而食堂门前施工虽然也截断了原来通向 ...

  7. kuangbin专题十二 HDU1078 FatMouse and Cheese )(dp + dfs 记忆化搜索)

    FatMouse and Cheese Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

  8. springboot整合activemq(三)配置文件

    application.properties文件配置: #服务端口,8080被另一服务占用server.port=9090spring.activemq.broker-url=tcp://127.0. ...

  9. java 解决Hash(散列)冲突的四种方法--开放定址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区

    java 解决Hash(散列)冲突的四种方法--开放定址法(线性探测,二次探测,伪随机探测).链地址法.再哈希.建立公共溢出区 标签: hashmaphashmap冲突解决冲突的方法冲突 2016-0 ...

  10. 【转】JavaScript里Function函数实现可变参数

    转载:  http://www.oschina.net/question/54100_15938 使用javascript类库函数时,经常会遇到一个函数,可以使用不同个数的参数的情况 比如:exp(v ...