MSMQ-發送消息到遠程專用隊列 實例


目錄

  1. 一:MSMQ的一些理論上的知識
  2. 二:隊列類型(Queue Type)
  3. 三:安裝消息隊列
  4. 四:在C#中Messagequeue class
  5. 五:MSMQ-發送消息到遠程專用隊列
  6. 六:例子
 

 

一、在學習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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM