一、在学习Messagequeue 类之前,首先介绍一下MSMQ的一些理论上的知识
          MSMQ(MicroSoft Message Queue,微软消息队列)官方的解释是:在多个不同的应用之间实现相互通信的一种异步传输模式,相互通信的应用可以分布于同一台机器上,也可以分布于相连的网络空间中的任一位置。MSMQ通过发送和接受消息使得应用程序之间的通信变的更快和更可靠。
     它的实现原理是:消息的发送者把自己想要发送的信息放入一个容器中(我们称之为Message),然后把它保存至一个系统公用空间的消息队列(Message Queue)中;本地或者是异地的消息接收程序再从该队列中取出发给它的消息进行处理。
          在消息传递机制中,有两个比较重要的概念。一个是消息,一个是队列。消息是由通信的双方所需要传递的信息,说白了它可以是各式各样的媒体,如文本、声音、图象,在我们编程的时候,它一般是一个类的对象或字符串等,消息最终的理解方式,为消息传递的双方事先商定,这样做的好处是,一是相当于对数据进行了简单的加密,二则采用自己定义的格式可以节省通信的传递量。队列是发送和接收消息的公用存储空间,它可以存在于内存中或者是物理文件中。
          采用MSMQ带来的好处是:由于是异步通信,无论是发送方还是接收方都不用等待对方返回成功消息,就可以执行余下的代码,因而大大地提高了事物处理的能力;当信息传送过程中,信息发送机制具有一定功能的故障恢复能力;MSMQ的消息传递机制使得消息通信的双方具有不同的物理平台成为可能。在微软的.net平台上利用其提供的MSMQ功能,可以轻松创建或者删除消息队列、发送或者接收消息、甚至于对消息队列进行管理。

二:队列类型(Queue Type)
          由您或网络中的其他用户创建的队列和系统队列。用户创建的队列可能是以下任何一种队列: 
          “公共队列”在整个“消息队列”网络中复制,并且有可能由网络连接的所有站点访问。 
          “专用队列”不在整个网络中发布。相反,它们仅在所驻留的本地计算机上可用。专用队列只能由知道队列的完整路径名或标签的应用程序访问。 
          “管理队列”包含确认在给定“消息队列”网络中发送的消息回执的消息。指定希望 MessageQueue 组件使用的管理队列(如果有的话)。       
          “响应队列”包含目标应用程序接收到消息时返回给发送应用程序的响应消息。指定希望 MessageQueue 组件使用的响应队列(如果有的话)。 
           系统生成的队列一般分为以下几类: “日记队列”可选地存储发送消息的副本和从队列中移除的消息副本。每个“消息队列”客户端上的单个日记队列存储从该计算机发送的消息副本。在服务器上为每个队列创建了一个单独的日记队列。此日记跟踪从该队列中移除的消息。 “死信队列”存储无法传递或已过期的消息的副本。如果过期或无法传递的消息是事务性消息,则被存储在一种特殊的死信队列中,称为“事务性死信队列”。死信存储在过期消息所在的计算机上。有关超时期限和过期消息的更多信息,请参见默认消息属性。 “报告队列”包含指示消息到达目标所经过的路由的消息,还可以包含测试消息。每台计算机上只能有一个报告队列。 “专用系统队列”是一系列存储系统执行消息处理操作所需的管理和通知消息的专用队列。 在应用程序中进行的大多数工作都涉及访问公共队列及其消息。但是,根据应用程序的日记记录、确认和其他特殊处理需要,在日常操作中很可能要使用几种不同的系统队列。

三:安装消息队列

如果你相使用消息队列进行通信的话,你就必须在你的电脑上安装消息队列,通过组件安装,具体安装的方法在这里就不详解了,类似于安装IIS一样

 

  对消息队列有了简单的了解后,使用MSMQ进行软件开发需要安装MSMQ,安装完后就该进入实际的开发阶段。具体的安装过程就是在控制面板里“添加/删除程序”下“添加/删除Windows组件”,完成添加就OK。安装完成后就可以通过交互界添加新的消息队列,详细如下图:

  

出了上面这种交互界面来创建MSMQ外,也可以通过编程来完成。

四:在C#中Messagequeue class

在使用.net开发msmq时,你必须引入命名空System.Messaging

MessageQueue 支持两种消息类型,同步和异步,同步方法使用的是peek();receive();异步使用的是:

Beginpeek() and Beginreceive();两者没有什么本质区别,都是封装好的方法,你只要直接创建Messagequeue的对象来调用这个方法就OK了, 我想至于什么同步和异步是什么意思,就没有必有解释了吧,

五:MSMQ-发送消息到远程专用队列

在工作组模式下,远程访问专用队列。在网上找到一篇文章,翻译了一下。
最后结论,直接使用多元素格式名方式,利用IP地址直接对单个或多个目标发送消息
MessageQueue rmQ = new MessageQueue("FormatName:Direct=TCP:121.0.0.1//private$//queue,Direct=TCP:192.168.1.2//private$//queue");
rmQ.Send("sent to regular queue - Atul");
原文地址
http://www.infosysblogs.com/microsoft/2007/02/msmq_sending_message_to_remote.html
 
1.当需要引用远程队列时,使用“machinename/private$/queuename”的格式无法工作。会返回“invalid queue path”错误。
 
 
2.队列名称需要使用“"FormatName:Direct=OS:machinename//private$//queuename”的格式。其他友好形式的表达式都是被转换为FormatName格式之后进行调用的。而且其他这些友好表达式的转换是基于Active Directory(域)来进行解析的,如果没有域的支持,这些表达式将无法工作。
 
例:
    MessageQueue rmQ = new MessageQueue 
                                    ("FormatName:Direct=OS:machinename//private$//queue");
    rmQ.Send("sent to regular queue - Atul");
 
 
3.FontName是区分大小写的。如果表达式为“FORMATNAME:Direct=OS:machinename//private$//queuename”,是无法工作的。但这种表达式不会返回任何错误。FontName好像是表达式里唯一区分大小写的部分。其他部分可以随意使用大小写,例如可以使用“DIRECT”。
 
 
4.如果想要使用机器IP地址,表达式的语法为“FormatName:Direct=TCP:ipaddress//private$//queuename”
 
  例:
     MessageQueue rmQ = new MessageQueue
                                     ("FormatName:Direct=TCP:121.0.0.1//private$//queue");
     rmQ.Send("sent to regular queue - Atul");
 
 
5.在代码中创建的队列实例对象的事务性属性,必须与要发送的目标队列的属性相匹配。前面的例子中发送的消息为非事务型消息,如果要发送消息到事务型的队列,代码为:
    MessageQueue rmTxnQ = new MessageQueue
                                            ("FormatName:Direct=OS:machinename//private$//queue");
    rmTxnQ.Send("sent to Txn queue - Atul", MessageQueueTransactionType.Single);
 
如果事务型属性不匹配,消息将无法传递。系统不会返回任何错误,但该条消息却会丢掉。
 
 
6.最后,当你发送消息到远程队列,系统会在本机创建一个临时的传出队列。这样做的目的是防止远程队列无法访问。在计算机管理器中查看消息队列/传出队列,可以看到这些临时队列。在管理器的右侧可以显示状态(联通、未联通)以及IP地址。

六:例子

------------------------------------------------------------------------------

using System;

using System.Collections.Generic;

using System.Text;

using System.Messaging;

namespace MyQueue

{

public class MyMessageQueue

{

private string Path;

/// <summary>

/// 1.通过Create方法创建使用指定路径的新消息队列

/// </summary>

/// <param name="queuePath"></param>

public void Createqueue(string queuePath)

{

try

{

if (!MessageQueue.Exists(queuePath))

{

MessageQueue.Create(queuePath);

}

else

{

Console.WriteLine(queuePath + "已经存在!");

//MessageQueue.Delete(queuePath);

//MessageQueue.Create(queuePath);

//Console.WriteLine(queuePath + "删除重建");

}

Path = queuePath;

}

catch (MessageQueueException e)

{

Console.WriteLine(e.Message);

}

}

/// <summary>

///  2.连接消息队列并发送消息到队列

/// 远程模式:MessageQueue rmQ = new MessageQueue("FormatName:Direct=OS:machinename//private$//queue");

///     rmQ.Send("sent to regular queue - Atul");对于外网的MSMQ只能发不能收

/// </summary>

public void SendMessage()

{

try

{

//连接到本地队列

MessageQueue myQueue = new MessageQueue(Path);

//MessageQueue myQueue = new MessageQueue("FormatName:Direct=TCP:192.168.12.79//Private$//myQueue1");

//MessageQueue rmQ = new MessageQueue("FormatName:Direct=TCP:121.0.0.1//private$//queue");--远程格式

Message myMessage = new Message();

myMessage.Body = "消息内容34kuangbo去死";

myMessage.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });

//发生消息到队列中

myQueue.Send(myMessage);

Console.WriteLine("消息发送成功!");

Console.ReadLine();

}

catch (ArgumentException e)

{

Console.WriteLine(e.Message);

}

}

/// <summary>

/// 3.连接消息队列并从队列中接收消息

/// </summary>

public void ReceiveMessage()

{

MessageQueue myQueue = new MessageQueue(Path);

myQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });

try

{

//从队列中接收消息

Message myMessage = myQueue.Receive();// myQueue.Peek();--接收后不消息从队列中移除

string context = myMessage.Body.ToString();

Console.WriteLine("消息内容:" + context);

Console.ReadLine();

}

catch (MessageQueueException e)

{

Console.WriteLine(e.Message);

}

catch (InvalidCastException e)

{

Console.WriteLine(e.Message);

}

}

/// <summary>

/// 4.清空指定队列的消息

/// </summary>

public void ClealMessage()

{

MessageQueue myQueue = new MessageQueue(Path);

myQueue.Purge();

Console.WriteLine("已清空对了{0}上的所有消息",Path);

}

/// <summary>

/// 5.连接队列并获取队列的全部消息

/// </summary>

public void GetAllMessage()

{

MessageQueue myQueue = new MessageQueue(Path);

Message[] allMessage = myQueue.GetAllMessages();

XmlMessageFormatter formatter = new XmlMessageFormatter(new Type[] { typeof(string) });

for (int i = 0; i < allMessage.Length; i++)

{

allMessage[i].Formatter = formatter;

Console.WriteLine("第{0}机密消息为:{1}", i+1, allMessage[i].Body.ToString());

}

Console.ReadLine();

}

}

}

------------------------
using System;
using System.Collections.Generic;
using System.Text;
namespace MyQueue
{
    class Program
    {
        static void Main(string[] args)
        {
            MyMessageQueue queue = new MyMessageQueue();
            queue.Createqueue(".//Private$//myQueue2");
            queue.SendMessage();
            queue.GetAllMessage();
            //queue.ReceiveMessage();
            //queue.ClealMessage();
        }
    }
}

注意:传输的 路径格式 要正确。

出处:http://blog.csdn.net/sage425/article/details/6298461

NET中MSMQ的使用----附例子的更多相关文章

  1. [转]从普通DLL中导出C++类 – dllexport和dllimport的使用方法(中英对照、附注解)

      这几天写几个小程序练手,在准备将一个类导出时,发现还真不知道如果不用MFC的扩展DLL,是怎么导出的.但我知道dllexport可以导出函数和变量,而且MFC扩展DLL就算是使用了MFC的功能,但 ...

  2. ASE存储过程和IQ存储过程的常见区别(附例子)

    ASE存储过程和IQ存储过程的常见区别(附例子) 1 存储过程简介 存储过程(Stored Procedure)是为了完成特定的功能而汇集成一组的SQL语句集,并为该组SQL语句命名.经编译后存储在S ...

  3. 我教女朋友学编程html系列(5) html中table的用法和例子

    女朋友不是学计算机的,但是现在从事计算机行业,做技术支持,她想学习编程,因此我打算每天教她一点点,日积月累,带她学习编程,如果其他初学者感兴趣,可以跟着学. 为了将table介绍的简单.生动,具有实战 ...

  4. Android中Service的一个Demo例子

    Android中Service的一个Demo例子  Service组件是Android系统重要的一部分,网上看了代码,很简单,但要想熟练使用还是需要Coding.  本文,主要贴代码,不对Servic ...

  5. 【ABAP系列】SAP ABAP中ALV使用HTML的例子

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP中ALV使用HT ...

  6. Java中连接MySql数据库的例子

    Java中连接MySql数据库的例子: package com.joinmysql.demo; import java.sql.DriverManager; import java.sql.Resul ...

  7. PHP中递归的实现(附例子)

    递归函数是一种调用自己的函数.写递归函数时要小心,因为可能会无穷递归下去.必须确保有充分的方法来终止递归. 一:使用参数引用完成递归函数.操作的是同一块内存地址. <?php $i=1; fun ...

  8. QT中静态库的生成与使用——创建共享库代码,附例子

    一. 静态库的生成    1. 测试目录: lib    2. 源码文件名: mywindow.h, mywindow.cpp, 类MyWindow继承于QPushButton, 并将文字设置为&qu ...

  9. js变量及其作用域(附例子及讲解)

    Javascript和Java.C这些语言不同,它是一种无类型.弱检测的语言.它对变量的定义并不需要声明变量类型,我们只要通过赋值的形式,可以将各种类型的数据赋值给同一个变量   工具/原料   Ch ...

随机推荐

  1. 【原/转】opencv的级联分类器训练与分类全程记录

    众所周知,opencv下有自带的供人脸识别以及行人检测的分类器,也就是说已经有现成的xml文件供你用.如果我们不做人脸识别或者行人检测,而是想做点其他的目标检测该怎么做呢?答案自然是自己训练一个特定的 ...

  2. 朝花夕拾-android 从手机选择图片或拍照设置头像

    Demo源码位置:http://git.oschina.net/zj2012zy/Android-Demo/tree/master/AndroidDemo/headset 一般需要用户信息的好多的也需 ...

  3. 配置gitlab gerrit jenkins

    配置gerrit 在gerrit创建jenkins用户 把jenkins用户加入Non-Interactive的组中 Projects -> List -> All-Projects Pr ...

  4. 未能找到元数据文件“引用的DLL的路径”

    使用VS的时候   偶尔会出现错误 [未能找到元数据文件“引用的DLL的路径”] 但是实际上项目中这些DLL都是做了引用的,甚至你前一天打开还是好好的,睡一觉起来 不知道什么原因 就酱紫了 原因:不详 ...

  5. VISUAL STUDIO 调试

    调试术语 Visual Studio调试之断点基础篇 Visual Studio调试之断点进阶篇 不能设置断点的检查步骤 Visual Studio调试之断点技巧篇 Visual Studio调试之断 ...

  6. Java异常信息处理

    import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import org.jun ...

  7. C++ pair用法

    Pair类型概述 pair是一种模板类型,其中包含两个数据值,两个数据的类型可以不同 1.定义(构造): 1 pair<int, double> p1; //使用默认构造函数 2 pair ...

  8. redis watch multi exec 关系

    EXEC 执行所有事务块内的命令. 假如某个(或某些) key 正处于 WATCH 命令的监视之下,且事务块中有和这个(或这些) key 相关的命令,那么EXEC 命令只在这个(或这些) key 没有 ...

  9. Hadoop blocks

    一In cases where the last record in a block is incomplete, the input split includes location informat ...

  10. [转]jQuery插件实现模拟alert和confirm

    本文转自:http://www.jb51.net/article/54577.htm (function () { $.MsgBox = { Alert: function (title, msg) ...