1、MSMQ——消息的響應(響應隊列)
若是須要從接收程序中得到比確認消息更多的信息(消息確認參考二),就可使用響應隊列。響應隊列相似於通常隊列,但原始發生程序吧該隊列用做接收程序,原始接收html
程序把響應隊列做用於發生程序。服務器
發送程序必須用 Message 類的 ResponseQueue 屬性指定響應隊列。在響應消息中,把 CorrelationId 屬性設置爲原始的消息ID,這樣,客戶端就知道該條應答屬於哪條消息。ide
這相似於確認隊列。響應消息用 MessageQueue 對象的 Send() 方法發送,MessageQueue 對象從 ResponseQueue 屬性中返回。 post
當消息隊列生成確認或報告消息時,它使用相關標識符屬性來指定原始消息的消息標識符。 這樣,相關標識符就可將報告或確認消息與原始消息關聯起來。加密
發送應用程序而後能夠進行匹配的確認或與原始消息的報表經過使用CorrelationId屬性來標識原始消息的Id屬性。url
鏈接器應用程序還必須設置 CorrelationId 屬性發送到原始消息的消息標識符的確認消息和報告的消息。spa
當你的應用程序將響應消息發送到發送應用程序時,能夠設置 CorrelationId 響應消息的原始消息的消息標識符的屬性。 發送應用程序而後能夠將響應消息與已發送的消息進行匹配。線程
/// <summary> /// 消息隊列 /// </summary> private MessageQueue messageQueue { get { string path = ".\\private$\\temp"; if (MessageQueue.Exists(path)) { //若是存在指定路徑的消息隊列,則獲取 return new MessageQueue(path); } else { //不存在,則建立新的 return MessageQueue.Create(path); } } } /// <summary> /// 獲取返回消息 /// </summary> public void ReciveMessage() { while (true) { //Message.Receive()是同步進行的,若是隊列中沒有消息,會阻塞當前線程 Message message = messageQueue.Receive(); message.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); string msg = message.Body.ToString(); var responeMessage = new Message("responeMessage") { //原始消息id CorrelationId = message.Id }; message.ResponseQueue = GetResponseQueue(); //獲取或設置一個值,該值指示發送方 ID 是否應附在消息中。 //message.AttachSenderId = true; //發生響應消息 message.ResponseQueue.Send(responeMessage); Console.WriteLine(msg); } }
獲取響應消息,得到原消息id進行匹配code
1 /// <summary> 2 /// 獲取響應隊列 3 /// </summary> 4 /// <returns></returns> 5 public MessageQueue GetResponseQueue() 6 { 7 //路徑 8 string path = ".\\private$\\ResponseQueue"; 9 if (MessageQueue.Exists(path)) 10 { 11 //若是存在指定路徑的消息隊列,則獲取 12 return new MessageQueue(path); 13 } 14 else 15 { 16 //不存在,則建立新的 17 return MessageQueue.Create(path); 18 } 19 } 20 21 /// <summary> 22 /// 獲取返回隊列消息 23 /// </summary> 24 public void ReciveResponseQueue() 25 { 26 while (true) 27 { 28 var myQueue = GetResponseQueue(); 29 //設置將獲取 CorrelationId 的MessageReadPropertyFilter設爲TRUE 30 myQueue.MessageReadPropertyFilter.CorrelationId = true; 31 //Message.Receive()是同步進行的,若是隊列中沒有消息,會阻塞當前線程 32 Message message = myQueue.Receive(); 33 34 message.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); 35 string msg = message.Body.ToString(); 36 //獲取原始消息的Id 37 var _correlationId = message.CorrelationId; 38 message.ResponseQueue = GetResponseQueue(); 39 40 Console.WriteLine(msg); 41 } 42 }
2、MSMQ——消息的確認
能夠將MessageQueue對象設置爲生成確認消息,能通知消息發送者消息是否已經成功傳遞。 orm
有兩種主要的確認類型:
·消息到達目標隊列的確認
·目標應用程序從隊列中檢索到消息的確認
確認是經過向隊列發送新消息來處理的。這種狀況下,確認消息從目標隊列發送到一個特殊類型的隊列中:管理隊列。確認消息不一樣於標準消息,由於它們不包含正文;在確認中,消息頭中的信息最重要。
這裏以一個示例來演示一下:
(一)新建管理隊列
private MessageQueue CreateAdminQueue()
{
string trPath = @".\Private$\selfAdminQueue";
MessageQueue _queue;
if (!MessageQueue.Exists(trPath))
return MessageQueue.Create(trPath);
_queue = new MessageQueue(trPath);
return _queue;
}
(二)傳遞消息
public void SendConfirmMessage(string strMsg)
{
MessageQueue _queue = CreateQueue();
Message _message = new Message(strMsg);
_message.AdministrationQueue = CreateAdminQueue();
_message.AcknowledgeType =
AcknowledgeTypes.PositiveReceive
| AcknowledgeTypes.PositiveArrival;
_queue.Send(_message);
}
·設置AdminstrationQueue的屬性。這個屬性是用來設置和獲取接收消息隊列的確認消息的隊列。
·設置確認消息屬性AcknowledgeType。這個屬性是用來設置和獲取返回給發送方消息確認的類型,它是個枚舉類型。枚舉值:
PositiveArrival |
一個掩碼,用於在原始消息到達隊列時請求確定確認。 |
PositiveReceive |
一個掩碼,用於在成功從隊列檢索到原始消息時請求確定確認。 |
NegativeReceive |
一個掩碼,用於當未能從隊列接收原始消息時請求否認確認。 |
None |
一個掩碼,用於請求不發送任何確認消息(不管是確定的仍是否認的)。 |
NotAcknowledgeReachQueue |
一個掩碼,用於在原始消息不能到達隊列時請求否認確認。當到達隊列時間計時器過時時或不能對消息進行身份驗證時,可能請求否認確認。 |
NotAcknowledgeReceive |
一個掩碼,用於當發生錯誤時請求否認確認,防止在其接收時間計時器過時前從隊列接收原始消息。 |
FullReachQueue |
一個掩碼,用於在原始消息到達隊列時請求確定確認,或者用於到達隊列時間計時器過時後請求否認確認,或者用於不能對原始消息進行身份驗證時請求否認確認。 |
FullReceive |
一個掩碼,用於在接收時間計時器過時前從隊列收到原始消息時請求確定確認,不然請求否認確認。 |
(三)接收方
public string GetNormalMessage()
{
MessageQueue _queue = CreateQueue();
_queue.Formatter =
new XmlMessageFormatter(new Type[] { typeof(string) });
Message _message = _queue.Receive();
return _message.Id;
}
接收消息正常接收。而後獲得消息的Id,經過Id來獲取在管理隊列中的管理消息的信息
(四)管理隊列消息
public void GetAcknowledgmentMessage(string strMsgId)
{
MessageQueue _queue = CreateAdminQueue();
_queue.MessageReadPropertyFilter.CorrelationId = true;
_queue.MessageReadPropertyFilter.Acknowledgment = true;
try
{
while (_queue.PeekByCorrelationId(strMsgId) != null)
{
Message myAcknowledgmentMessage =
_queue.ReceiveByCorrelationId(strMsgId);
Console.WriteLine("Correlation Id: "
+ myAcknowledgmentMessage.CorrelationId.ToString());
Console.WriteLine("Id: "
+ myAcknowledgmentMessage.Id.ToString());
Console.WriteLine("Acknowledgment Type: "
+ myAcknowledgmentMessage.Acknowledgment.ToString());
}
}
catch
{ }
}
經過消息標識來檢索管理隊列,檢索成功打印信息。確認類型Acknowledgment用於指定嘗試的消息傳遞的結果。它是個枚舉:
None |
該消息不是確認消息。 |
AccessDenied |
一個否認到達確認,它指示發送應用程序不具備將消息發送到目標隊列所需的權限。 |
BadDestinationQueue |
一個否認到達確認,它指示目標隊列不可用於發送應用程序。 |
BadEncryption |
一個否認到達確認,它指示目標隊列管理器未能解密私有消息。 |
BadSignature |
一個否認到達確認,它指示原始消息的數字簽名無效而且未能由消息隊列進行身份驗證。 |
CouldNotEncrypt |
一個否認到達確認,它指示源隊列管理器未能加密私有消息。 |
HopCountExceeded |
一個否認到達確認,它指示已超出了原始消息的跳數(跳數指示中間服務器的數目)。 |
NotTransactionalQueue |
一個否認到達確認,它指示已將事務性消息發送到非事務性隊列。 |
NotTransactionalMessage |
一個否認到達確認,它指示非事務性消息被髮送到了事務性隊列。 |
Purged |
一個否認到達確認,它指示消息在到達其目標隊列前已被清除。 |
QueueDeleted |
一個否認讀取確認,它指示在能夠讀取消息前隊列已被刪除。 |
QueueExceedMaximumSize |
一個否認到達確認,它指示原始消息因其目標隊列已滿而未被傳送。 |
QueuePurged |
一個否認讀取確認,它指示在能夠讀取消息前隊列已被清除。 |
ReachQueue |
一個確定到達確認,它指示原始消息已到達其目標隊列。 |
ReachQueueTimeout |
一個否認到達確認,它指示在原始消息可到達目標隊列前到達隊列時間計時器或接收時間計時器已過時。 |
ReceiveTimeout |
一個否認讀取確認,它指示在其接收時間計時器過時前沒有從隊列接收原始消息。 |
Receive |
一個確定讀取確認,它指示原始消息已由接收應用程序接收 |
(五)流程
·當向消息隊列傳遞消息時,同時向管理隊列傳遞了消息(當消息隊列收到消息後,管理隊列中也會收到消息)。此時的消息是:消息已經到達消息隊列。(在管理隊列中的消息是不帶包體正文的,因此說頭最重要。)
·當從消息隊列中接收到消息後(此時消息的標識已經讀出),消息隊列消息就會清空(Revceive的)。而後在管理隊列中就會再多一條管理消息,來標示:消息已經被接收。
·當處理管理隊列消息時,會按消息標識來處理管理隊列消息。