NET中MSMQ的使用----附例子

 

 

1、在學習Messagequeue 類以前,首先介紹一下MSMQ的一些理論上的知識
          MSMQ(MicroSoft Message Queue,微軟消息隊列)官方的解釋是:在多個不一樣的應用之間實現相互通訊的一種異步傳輸模式,相互通訊的應用能夠分佈於同一臺機器上,也能夠分佈於相連的網絡空間中的任一位置。MSMQ經過發送和接受消息使得應用程序之間的通訊變的更快和更可靠。
     它的實現原理是:消息的發送者把本身想要發送的信息放入一個容器中(咱們稱之爲Message),而後把它保存至一個系統公用空間的消息隊列(Message Queue)中;本地或者是異地的消息接收程序再從該隊列中取出發給它的消息進行處理。
          在消息傳遞機制中,有兩個比較重要的概念。一個是消息,一個是隊列。消息是由通訊的雙方所須要傳遞的信息,說白了它能夠是各式各樣的媒體,如文本、聲音、圖象,在咱們編程的時候,它通常是一個類的對象或字符串等,消息最終的理解方式,爲消息傳遞的雙方事先商定,這樣作的好處是,一是至關於對數據進行了簡單的加密,二則採用本身定義的格式能夠節省通訊的傳遞量。隊列是發送和接收消息的公用存儲空間,它能夠存在於內存中或者是物理文件中。
          採用MSMQ帶來的好處是:因爲是異步通訊,不管是發送方仍是接收方都不用等待對方返回成功消息,就能夠執行餘下的代碼,於是大大地提升了事物處理的能力;當信息傳送過程當中,信息發送機制具備必定功能的故障恢復能力;MSMQ的消息傳遞機制使得消息通訊的雙方具備不一樣的物理平臺成爲可能。在微軟的.net平臺上利用其提供的MSMQ功能,能夠輕鬆建立或者刪除消息隊列、發送或者接收消息、甚至於對消息隊列進行管理。編程

二:隊列類型(Queue Type)
          由您或網絡中的其餘用戶建立的隊列和系統隊列。用戶建立的隊列多是如下任何一種隊列: 
          「公共隊列」在整個「消息隊列」網絡中複製,而且有可能由網絡鏈接的全部站點訪問。 
          「專用隊列」不在整個網絡中發佈。相反,它們僅在所駐留的本地計算機上可用。專用隊列只能由知道隊列的完整路徑名或標籤的應用程序訪問。 
          「管理隊列」包含確認在給定「消息隊列」網絡中發送的消息回執的消息。指定但願 MessageQueue 組件使用的管理隊列(若是有的話)。       
          「響應隊列」包含目標應用程序接收到消息時返回給發送應用程序的響應消息。指定但願 MessageQueue 組件使用的響應隊列(若是有的話)。 
           系統生成的隊列通常分爲如下幾類: 「日記隊列」可選地存儲發送消息的副本和從隊列中移除的消息副本。每一個「消息隊列」客戶端上的單個日記隊列存儲從該計算機發送的消息副本。在服務器上爲每一個隊列建立了一個單獨的日記隊列。此日記跟蹤從該隊列中移除的消息。 「死信隊列」存儲沒法傳遞或已過時的消息的副本。若是過時或沒法傳遞的消息是事務性消息,則被存儲在一種特殊的死信隊列中,稱爲「事務性死信隊列」。死信存儲在過時消息所在的計算機上。有關超時期限和過時消息的更多信息,請參見默認消息屬性。 「報告隊列」包含指示消息到達目標所通過的路由的消息,還能夠包含測試消息。每臺計算機上只能有一個報告隊列。 「專用系統隊列」是一系列存儲系統執行消息處理操做所需的管理和通知消息的專用隊列。 在應用程序中進行的大多數工做都涉及訪問公共隊列及其消息。可是,根據應用程序的日記記錄、確認和其餘特殊處理須要,在平常操做中極可能要使用幾種不一樣的系統隊列。服務器

三:安裝消息隊列網絡

若是你相使用消息隊列進行通訊的話,你就必須在你的電腦上安裝消息隊列,經過組件安裝,具體安裝的方法在這裏就不詳解了,相似於安裝IIS同樣併發

 

 ASP.NET中進行消息處理(MSMQ) 一

  對消息隊列有了簡單的瞭解後,使用MSMQ進行軟件開發須要安裝MSMQ,安裝完後就該進入實際的開發階段。具體的安裝過程就是在控制面板裏「添加/刪除程序」下「添加/刪除Windows組件」,完成添加就OK。安裝完成後就能夠經過交互界添加新的消息隊列,詳細以下圖:異步

 

  ASP.NET中進行消息處理(MSMQ) 一

出了上面這種交互界面來建立MSMQ外,也能夠經過編程來完成。學習

四:在C#中Messagequeue class測試

在使用.net開發msmq時,你必須引入命名空System.Messaging加密

MessageQueue 支持兩種消息類型,同步和異步,同步方法使用的是peek();receive();異步使用的是:spa

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

相關文章
相關標籤/搜索