对MSMQ的介绍:
MSMQ是message queuing的简写,是由微软提供用于轻量级的通信服务组件。它与及时通信有很大的不同,及时通信要求客户端与服务端要同时通行(要对请求给予及时的回应),就像打电话一样,要求发送方与接受方同时在线。MSMQ可以要求在线和不在线的时候都能够通信。可以将这种技术用到电子邮件,电子商务中的定单处理。他的工作原理:
在客户端消息发送程序将消息发送到消息队列中
在服务器端接受消息队列接受来自客户的消息,然后在将消息发送给消息接受处理程序
说明:消息发送程序可能在一段时间发送大量消息但是服务端来不及处理时,所有消息被存储在队列中只有当服务端可以处理时在来对所有的消息进行处理,所有的消息不会丢失。当然在客户端和服务端在断线时,也可以发送消息,存储在消息队列中不丢失消息,当连线时在把队列中消息发送到服务端进行处理。
在MSMQ中,总共定义了8种类型的队列:
1,公共消息队列:公共消息队列发布在Active Directory列表中并被复制到Windows2000域中。可以不用知道消息队列所在的计算机名称而去浏览或搜索公共队列,因而可以把消息队列从一台计算机移动到另一台计算机上,并不对客户端程序造成影响。
2,私有消息队列:只能在没有专用Message Queuing 服务器的工作组环境中使用,他们不支持身份验证,且没有计算机名称就不能定位消息队列。这些队列通常用于安全部署系统前的开发测试或在小规模系统中使用。
3,待发队列:它是本地内部队列,它用于在消息发送到目的(远程)队列之前存储消息。如果计算机不在线,消息在待发队列中存储很长时间并在重新建立连接后自动发送消息。它是自动生成,并不能手动删除或创建。
4,连接器队列:
5,日志队列:日志队列包含已经发送或处理了的消息副本,以供应用。日志分为两类日志:源日志(按消息处理)和目标日志(按队列管理)。
6,死信队列:包含没有发送成功的过期的消息。事务消息队列存储在单独的事务死信队列中。
消息无法发送的原因有:
1,队列以满,不能找到队列或不知道发送方。
2,非事务性的消息被发送到事务消息队列中或取而代之。
3,消息超过了最大活跃点或超过了最大生命期。消息可能超过队列到达时间限制或接受时间限制。这两个限制可以自己限定。
7,管理队列:管理队列存储消息回执。确定另一消息已被接收的消息。
8,汇报队列:如果消息路由跟踪已启用,则汇报队列用于跟踪已发送消息的路由。
MSMQ在.net中的应用:
在我们开始介绍消息队列在.net的应用前让我们先熟悉一下队列路径格式
队列类型 路径格式
公有队列: 机器名称\队列名称
私有队列: 机器名称\privates$\队列名称
日志队列: 机器名称\队列名称\Journal$
机器日志: 机器名称\Journals$
机器死信: 机器名称\DeadLetter$
机器事务死信: 机器名称\XactDeadLetter$
在离线下工作时,规则有一些变化:消息队列此时是不可用的,创建MessageQueue对象时要用到格式名称,例如:FormatName:PUBLIC=382c74c3-721d-4f34-80e5-5765b6cbc27。
队列路径格式:
队列类型 语法
公有队列: 格式名称:PUBLIC=[QueueGUID]
私有队列: 格式名称:PRIVATE=[MachineGUID]\[QueueNumber]
机器队列: 格式名称:DIRECT=OS:[MachineGUID]\[QueueNumber]
协议队列: 格式名称:DIRECT=[Protocol]:[MachineName]\[QueueNumber]
(协议队列格式在不同的系统中有不同格式,eg:MessageQueuing 3.0支持http协议,但2.0不支持)
现在开始我们对消息队列的研究:
在.net中引用System.Messing名称空间。在名称空间中提供了格式化、发送和接受消息,创建配置消息队列的所有类型。
让我们先看一段代码:
<Serialiezable()>
Public Class Order
{
Private string ordercode;
Prvate string clientName;
Prvate ArrayList Items;
Public Order(string _odercode,stirng _clientName,ArrayList _Items)
{
ordercode=_odercode;
clientName=_clientName;
Items=_Items;
}
Public string odercoder
{
Get{}
Set{}
}
.........................
}
Public class VN
{
Public void main()
{
Oder oder = new Oder("chaung","chiang",。。)
MessageQueue Queue;
If(Queue.Exists(".\TestQueue"))
Queue = new MessageQueue(".\TestQueue");
Else
Queue = queue.Create(".\TestQueue");
queue.Formatter = new BinaryMessageFormatter();
Queue.send(order,"testMessage");
}
}
上面的一段代码包含对消息队列的创建,同时也有给消息队列发送消息
我们通过Exits检测消息队列是否已有所要的队列,如果有就用此队列,如果没有就创建一个新的消息队列。
然后将消息队列Formatter属性;
最后将消息发送(Send方法)到队列中去;
我们还可以对消息进行高级的配制:
如下一段代码:
Order odr = new Order("234234234","sadfhweo");
Message ordMessage = new Message(odr);
ordMessage.UserEncryption = true;
ordMessage.EncryptionAlgorithm =Messaging.EncryptionAlgorithm.Rc2;
ordMessage.Priority = Messaging.MessagePriority.VeryHigh;
ordMessage.Recoverable = True;
.....................
Queue.send(ordMessage,"Encryptec Order");
当然Message中有许多的属性可以设置,可以在MSDN中查看这些属性;
消息接受
当然,我们已将消息发送到队列中去了,但是我们不能让消息永远放在队列中,我们也要把消息从消息队列中接受加以处理。我们可以通过如下的方法来实现它:
MessageQueue queue = new MessageQueue(".\TestQueue");
Message oderMessage = new Message();
Queue.Formatter = new BinaryMessageFormatter(Order)
While(1)
{
orderMessage = (Order)Queue.Receive();
Console.Write(orderMessage.ordercode);
}