当前位置:编程问答 > 网站相关 >

WCF后续之旅(16): 消息是如何分发到Endpoint的--消息筛选(Message Filter)

在介绍终结点的html#1320329" target=_blank>ListenUriMode时,我们提到了两个特殊的对象ChannelDispatcher和ChannelListener。这两个对象在整个WCF的消息分发系统中具有重要的地位,在这节里,我们对WCF的整个消息分发过程作一个简单的介绍。

一、连接请求的监听

当我们通过ServiceHost对某个服务进行寄宿的时候,实际上WCF是在为我们创建一个监听器,并监听来自外界的服务访问请求。我们举一个例子,比如针对服务CalculateService,具有如下的配置:该服务具有基于BasicHttpBinding的三个终结点,他们的地址(逻辑地址)分别为:http://127.0.0.1:9999/calculateservice,http://127.0.0.1:8888/calculateservice和http://127.0.0.1:7777/calculateservice,而前两个共享同一个ListenUri——http://127.0.0.1:6666/calculateservice。而第三个使用默认的ListenUri(也就是终结点地址)。

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>   
   3:     <system.serviceModel>
   4:         <services>
   5:             <service name="Artech.WcfServices.Services.CalculateService">
   6:                 <endpoint address="http://127.0.0.1:9999/calculateservice" binding="basicHttpBinding"
   7:                     contract="Artech.WcfServices.Contracts.ICalculate" listenUri="http://127.0.0.1:6666/calculateservice" />
   8:                 <endpoint address="http://127.0.0.1:8888/calculateservice" binding="basicHttpBinding"
   9:                     contract="Artech.WcfServices.Contracts.ICalculate" listenUri="http://127.0.0.1:6666/calculateservice" />
  10:                 <endpoint address="http://127.0.0.1:7777/calculateservice" binding="basicHttpBinding"
  11:                     contract="Artech.WcfServices.Contracts.ICalculate" />
  12:             </service>
  13:         </services>
  14:     </system.serviceModel>
  15: </configuration>
  16: 

 

当我们通过ServiceHost对该服务进行寄宿的时候,会为该服务创建一个ServiceHost对象。当我们执行ServiceHost的Open方法的时候,WCF会创建两个ChannelDispatcher对象。为什么会是两个ChannelDispatcher对象呢?这是因为ChannelDispatcher是根据实际的监听地址创建的,在本例中,虽然我们为服务创建了三个终结点,由于前两个共享同一个监听地址,所所以针对于服务的ServiceHost对象,具有两个ChannelDispatcher对象与之匹配。对于每个ChannelDispatcher对象而言,他们各自对应一个唯一的ChannelListener对象,ChannelListener具有两个方面的作用,其一是绑定到一个具体的URI,监听来自外界的连接请求,其二就是当检测到请求后,创建信道堆栈(channel stack)接受、处理请求。ServiceHost的Open方法的执行,同时也预示着ChannelListener监听工作的开始。

由于我们为该服务注册了三个终结点,WCF还会创建3个EndpointDispatcher对象,分别于三个终结点对应。对于服务访问请求的消息,会先被对应的ChannelDispacher(这取决于该消息是从哪个ChannelListener接收到的)接收,ChannelDispacher本身并不会对该消息进行处理,而是为将它转发到对应的EndpointDispatcher上,基于该消息的所有后续处理都叫由EndpointDispatcher进行处理。对于这三个EndpointDispatcher对象,前面两个和第一个ChannelDispatcher匹配(根据实际的监听地址进行匹配)。

总结一下,一个CalculateService服务,对应着一个ServiceHost对象。该ServiceHost对象有具有两个ChannelDispatcher对象,这两个ChannelDispatcher各自具有一个ChannelListener对象,他们对应的监听地址分别为http://127.0.0.1:6666/calculateservice和http://127.0.0.1:7777/calculateservice。对于前一个ChannelDispatcher,具有两个与之匹配的EndpointDispatcher对象,后一个具有一个匹配的EndpointDispatcher对象。具体关系如下图所示:

image

我们可以通过一个例子在正式这一点,完全针对我们上面提供的配置,我们通过下面的代码将该服务在一个控制台应用中进行寄宿,然后打印出ChannelDispatcher和EndpointDispatcher的关系:

   1: //---------------------------------------------------------------
   2: // EndpointAddress & WCF Addressing (c) by 2008 Jiang Jin Nan
   3: //---------------------------------------------------------------
   4: using System.ServiceModel;
   5: using Artech.WcfServices.Services;
   6: using System.Threading;
   7: using System;
   8: using System.ServiceModel.Dispatcher;
   9: 
  10: namespace Artech.WcfServices.Hosting
  11: {
  12:     class Program
  13:     {
  14:         static void Main(string[] args)
  15:         {
  16:             using (ServiceHost serviceHost = new ServiceHost(typeof(CalculateService)))
  17:             {
  18:                 serviceHost.Open();
  19:                 int i=0;
  20: 
  21:                 foreach (ChannelDispatcher channelDispatcher in serviceHost.ChannelDispatchers)
  22:                 {
  23:                     Console.WriteLine("ChannelDispatcher {0}: ListenUri: {1}", ++i, channelDispatcher.Listener.Uri);
  24:   

补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,