標籤:blog http io os 使用 ar for strong sp
目錄
- 一:MSMQ的一些理論上的知識
- 二:隊列類型(Queue Type)
- 三:安裝訊息佇列
- 四:在C#中Messagequeue class
- 五:MSMQ-發送訊息到遠程專用隊列
- 六:例子
一、在學習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的使用----附例子