`
varsoft
  • 浏览: 2504052 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

[WCF的Binding模型]之三:信道监听器(Channel Listener)

阅读更多

信道管理器是信道的创建者,一般来说信道栈的中每个信道对应着一个信道管理器。基于不同的消息处理的功能,将我们需要将相应的信道按照一定的顺序能组织起来构成一个信道栈,由于信道本身是由信道管理器创建的,所以信道对应的信道管理器也构成一个信道管理器栈,栈中信道管理器的顺序决定由它所创建信道的顺序。

对于WCF的信道层来说,信道管理器在服务端和客户端扮演着不同的角色,服务端的信道管理器在于监听来自客户端的请求,而客户端的信道仅仅是单纯的创建用于消息发送的信道。因此,客户端的消息管理器又称为信道监听器(Channel Listener),客户端的信道管理器则成为信道工厂(channel factory)。

在WCF中,所有的信道管理器,不管是位于服务端的信道监听器还是客户端的信道工厂,都继承自一个基类:System.ServiceModel.Channels.ChannelManagerBase。ChannelManagerBase直接继承自CommunicationObject,并实现了接口IDefaultCommunicationTimeouts。

   1: public abstract class ChannelManagerBase : CommunicationObject, IDefaultCommunicationTimeouts 
<!--CRLF-->
   2: { 
<!--CRLF-->
   3:    // ...... 
<!--CRLF-->
   4: }
<!--CRLF-->

其实我们完全可以把一个WCF应用开成是一个普通的基于监听-请求模式的网络应用,服务端将监听器绑定到一个或一组URI上进行网络监听,一旦成功监听到来自客户端的请求,则接收、处理该请求,如需回复则发送回复回客户端。在整个过程中,监听器处于核心的地位,而WCF中的信道监听器就起着这样的作用。

一、关于信道监听器的监听过程

熟悉网络编程的朋友一定会对套节字应用编程接口(Berkeley Sockets API)不会陌生,通过Socket API,我们很容易的创建基于网络监听-请求的应用程序。在.NET编程环境下,我们将System.Net.Sockets.TcpListener 或者System.Net.Sockets.Socket 对象绑定到一个URI上,让他们监听来自客户端的连接。当连接请求被成功监测到,调用Accept相关方法或者方法创建一Socket或者TcpClient对象,并通过这些对象获得请求消息。

WCF中的信道监听器与之相似。当我们对一个服务进行寄宿的时候,会为之添加一个或者多个终结点。对于一个终结点来说,它具有一个代表逻辑地址的终结点地址,还有一个代表物理地址的监听地址(关于逻辑地址和物理地址,请参阅第二章),如果监听地址(ListenUri)没有显式地指定,则监听地址和逻辑地址共享相同的URI。对于每一个不同监听地址,WCF会通过具体的绑定对象创建一个信道监听器。信道监听器通过调用AcceptChannel创建监听信道栈,位于信道栈的第一个信道被成功返回。

一旦消息请求被成功监听,如果该信道是InputChannel(数据报MEP) 或者DuplexChannel(双工MEP),则调用Receive或者BeginReceive方法接收消息,如果需要向对象发送消息,则通过Send或者BeginSend将消息发给请求者;如果信道是ReplyChannel(请求/回复MEP)则调用ReceiveRequest方法获得一个RequestContext对象,通过该对象获取请求消息并发送回复消息。

二、信道监听器相关的接口和基类

由于信道监听器是位于服务端的信道管理器,所以所有的信道监听器均继承自基类:ChannelManagerBase。同时由于信道监听器具有其特殊的请求监听的功能,所以WCF还定义一些相关的接口,比如System.ServiceModel.Channels.IChannelListener和System.ServiceModel.Channels.IChannelListener<TChannel>。

IChannelListener继承自ICommnucationObject接口。定义了一组WaitForChannel和BeginWaitForChannel/EndWaitForChannel以同步和异步的方式判断是否具有一个可用的信道;GetProperty<T>和IChannel的GetProperty<T>相对;Uri属性返回真正的监听地址。

   1: public interface IChannelListener : ICommunicationObject
<!--CRLF-->
   2: {
<!--CRLF-->
   3:     IAsyncResult BeginWaitForChannel(TimeSpan timeout, AsyncCallback callback, object state);
<!--CRLF-->
   4:     bool EndWaitForChannel(IAsyncResult result);
<!--CRLF-->
   5:     T GetProperty<T>() where T : class;
<!--CRLF-->
   6:     bool WaitForChannel(TimeSpan timeout);
<!--CRLF-->
   7: 
<!--CRLF-->
   8:     Uri Uri { get; }
<!--CRLF-->
   9: }
<!--CRLF-->

范型类型的IChannelListener<TChannel>继承自IChannelListener,范型类型TChannel是一个实现了IChannel的类,一般来说,TChannel代表基于某种channel shape的Channel, 比如实现了IOutputChannel、IInputChannel、IRequestChanne、IReplyChannel、IDuplexChannel的IChannel类型。定义在IChannelListener<TChannel>的AcceptChannel和BeginAcceptChannel/EndAcceptChannel在连接请求被监听到时,以同步或者异步的方式创建信道栈用于消息的接收。

   1: public interface IChannelListener<TChannel> : IChannelListener, ICommunicationObject where TChannel : class, IChannel
<!--CRLF-->
   2: {
<!--CRLF-->
   3:     // Methods
<!--CRLF-->
   4:     TChannel AcceptChannel();
<!--CRLF-->
   5:     TChannel AcceptChannel(TimeSpan timeout);
<!--CRLF-->
   6:     IAsyncResult BeginAcceptChannel(AsyncCallback callback, object state);
<!--CRLF-->
   7:     IAsyncResult BeginAcceptChannel(TimeSpan timeout, AsyncCallback callback, object state);
<!--CRLF-->
   8:     TChannel EndAcceptChannel(IAsyncResult result);
<!--CRLF-->
   9: }  
<!--CRLF-->

除了定义两个接口外,WCF中还定义了与这两个接口向对应的抽象基类:System.ServiceModel.Channels.ChannelListenerBase和System.ServiceModel.Channels.ChannelListenerBase<TChannel>。ChannelListenerBase实现了接口IChannelListener,而ChannelListenerBase<TChannel>实现了接口IChannelListener<TChannel>。

   1: public abstract class ChannelListenerBase : ChannelManagerBase, IChannelListener, ICommunicationObject
<!--CRLF-->
   2: { 
<!--CRLF-->
   3:     //... ...
<!--CRLF-->
   4: }
<!--CRLF-->
   5: public abstract class ChannelListenerBase<TChannel> : ChannelListenerBase, IChannelListener<TChannel>, IChannelListener, ICommunicationObject where TChannel : class, IChannel
<!--CRLF-->
   6: {
<!--CRLF-->
   7:     //... ...
<!--CRLF-->
   8: }
<!--CRLF-->

图1所示的类图大体上表示了上述的这些基类和接口之间的关系:

image

图1 信道监听器接口与基类

三、案例演示:如何自定义信道监听器

在上面一节的案例演示中,我们创建了两个用于请求-回复消息交换模式下的自定义信道,一个是实现了IRequestChannel的SimpleRequestChannel.,另一个是实现了IReplyChannel的SimpleReplyChannel。在本案例以及接下来的案例演示中,我们将为这两个自定义创建两个相应的信道管理器,其实一个是用于创建SimpleRequestChannel的自定义信道工厂,另一个则是创建SimpleReplyChannel的自定义信道监听器。先来看看我们自定义的信道监听器SimpleChannelListener<TChannel>。该类继承自范型的ChannelListenerBase<TChannel>:

   1: public class SimpleChannelListener<TChannel> : ChannelListenerBase<TChannel> where TChannel : class, IChannel
<!--CRLF-->
   2: {
<!--CRLF-->
   3:     //... ...
<!--CRLF-->
   4: }
<!--CRLF-->

我们说过信道一般不会孤立地存在,而是存在于一个由多个信道按照一定顺序构成的信道栈中。由于信道管理器是信道的缔造者,要创建整个信道栈,同样需要这些信道对应的信道管理器按照相应的顺序组成一个信道管理器栈。反映在具体实现上,当执行了某个方法之后,需要调用栈中后一个信道监听器相应的方法,所以在SimpleChannelListener<TChannel>中,定义一个字段_innerChanneListener,代表栈中与之相邻的信道监听器。_innerChanneListener通过在构造函数中指定的BindingContext对象创建。关于BindingContext,我将在后面的一节中左详细的介绍。

   1: public class SimpleChannelListener<TChannel> : ChannelListenerBase<TChannel> where TChannel : class, IChannel
<!--CRLF-->
   2: {
<!--CRLF-->
   3:     ... ...
<!--CRLF-->
   4:     private IChannelListener<TChannel> _innerChanneListener; 
<!--CRLF-->
   5: 
<!--CRLF-->
   6:     public SimpleChannelListener(BindingContext context)
<!--CRLF-->
   7:     {
<!--CRLF-->
   8:         PrintHelper.Print(this, "SimpleChannelListener");
<!--CRLF-->
   9:         this._innerChanneListener = context.BuildInnerChannelListener<TChannel>();
<!--CRLF-->
  10:     }
<!--CRLF-->
  11: }
<!--CRLF-->

对于SimpleChannelListener<TChannel>来说,它的最重要的功能就是创建我们自定义的ReplyChannel:SimpleReplyChannel。SimpleReplyChannel的创建实现在OnAcceptChannel和OnEndAcceptChannel方法中。在构造SimpleReplyChannel的innerChannel通过_innerChanneListener的AcceptChannel方法创建。

   1: public class SimpleChannelListener<TChannel> : ChannelListenerBase<TChannel> where TChannel : class, IChannel
<!--CRLF-->
   2: {
<!--CRLF-->
   3:     ... ... 
<!--CRLF-->
   4: 
<!--CRLF-->
   5:     protected override TChannel OnAcceptChannel(TimeSpan timeout)
<!--CRLF-->
   6:     {
<!--CRLF-->
   7:         PrintHelper.Print(this, "OnAcceptChannel");
<!--CRLF-->
   8:         IReplyChannel innerChannel = this._innerChanneListener.AcceptChannel(timeout) as IReplyChannel;
<!--CRLF-->
   9:         return new SimpleReplyChannel(this, innerChannel) as TChannel;
<!--CRLF-->
  10:     }
<!--CRLF-->
  11:     protected override IAsyncResult OnBeginAcceptChannel(TimeSpan timeout, AsyncCallback callback, object state)
<!--CRLF-->
  12:     {
<!--CRLF-->
  13:         PrintHelper.Print(this, "OnBeginAcceptChannel");
<!--CRLF-->
  14:         return this._innerChanneListener.BeginAcceptChannel(timeout, callback, state); 
<!--CRLF-->
  15: 
<!--CRLF-->
  16:     } 
<!--CRLF-->
  17: 
<!--CRLF-->
  18:     protected override TChannel OnEndAcceptChannel(IAsyncResult result)
<!--CRLF-->
  19:     {
<!--CRLF-->
  20:         PrintHelper.Print(this, "OnEndAcceptChannel");
<!--CRLF-->
  21:         return new  SimpleReplyChannel(this,this._innerChanneListener.EndAcceptChannel(result) as IReplyChannel) as TChannel;
<!--CRLF-->
  22:     }
<!--CRLF-->
  23: }
<!--CRLF-->

对于定义在基类必须实现的抽象方法来说,为了简单起见,我们仅仅是通过PrintHelper输出当前执行的方法名称,然后调用_innerChanneListener的相应的方法就可以了:

   1: public class SimpleChannelListener<TChannel> : ChannelListenerBase<TChannel> where TChannel : class, IChannel
<!--CRLF-->
   2: {
<!--CRLF-->
   3:       protected override IAsyncResult OnBeginWaitForChannel(TimeSpan timeout, AsyncCallback callback, object state)
<!--CRLF-->
   4:         {
<!--CRLF-->
   5:             PrintHelper.Print(this, "OnBeginWaitForChannel");
<!--CRLF-->
   6:             return this._innerChanneListener.BeginWaitForChannel(timeout, callback, state); 
<!--CRLF-->
   7:         } 
<!--CRLF-->
   8:         protected override bool OnEndWaitForChannel(IAsyncResult result)
<!--CRLF-->
   9:         {
<!--CRLF-->
  10:             PrintHelper.Print(this, "OnEndWaitForChannel");
<!--CRLF-->
  11:             return this._innerChanneListener.EndWaitForChannel(result);
<!--CRLF-->
  12:         } 
<!--CRLF-->
  13:         protected override bool OnWaitForChannel(TimeSpan timeout)
<!--CRLF-->
  14:         {
<!--CRLF-->
  15:             PrintHelper.Print(this, "OnWaitForChannel");
<!--CRLF-->
  16:             return this._innerChanneListener.WaitForChannel(timeout);
<!--CRLF-->
  17:         }
<!--CRLF-->
  18:     //... ...
<!--CRLF-->
  19: }
<!--CRLF-->
  20:  
<!--CRLF-->
  21: 
<!--CRLF-->

WCF中的绑定模型:
[WCF中的Binding模型]之一: Binding模型简介
[WCF中的Binding模型]之二: 信道与信道栈(Channel and Channel Stack)
[WCF中的Binding模型]之三:信道监听器(Channel Listener)
[WCF中的Binding模型]之四:信道工厂(Channel Factory)
[WCF中的Binding模型]之五:绑定元素(Binding Element)
[WCF中的Binding模型]之六:从绑定元素认识系统预定义绑定


分享到:
评论

相关推荐

    了解WCF内建Binding

    WCF(Windows Communication Foundation)作为Microsoft .NET Framework的一个核心组件,提供了丰富的通信功能,支持多种传输协议、编码格式和通信协议,而这些特性主要是通过其内建的Binding机制来实现的。...

    WCF分布式开发技术讲座

    **WCF分布式开发技术讲座** Windows Communication Foundation (WCF) 是微软.NET框架中的一项核心技术,用于构建可伸缩、安全且可靠的分布式应用程序。WCF整合了.NET Framework中的多种通信技术,如ASMX、Remoting...

    WCF开发实战

    WCF开发实战系列一:创建第一个WCF服务 WCF开发实战系列二:使用IIS发布WCF服务 WCF开发实战系列三:自运行WCF服务 WCF开发实战系列四:使用Windows服务发布WCF服务 WCF开发实战系列五:创建WCF客户端程序

    WCF之旅:一个简单的WCF程序(vs2010源码)

    **WCF之旅:一个简单的WCF程序** Windows Communication Foundation (WCF) 是微软.NET Framework中的一个核心组件,用于构建分布式应用程序。它提供了一种统一的编程模型,可以创建跨平台、安全、可靠的网络服务。...

    WCF简单模型

    **WCF(Windows Communication Foundation)简单模型** WCF(Windows Communication Foundation)是微软推出的一种面向服务的架构,它提供了一种统一的方式来进行分布式系统通信。这个“WCF简单模型”可能是一个...

    WCF https binding 实例

    IMySecureService serviceProxy = ChannelFactory&lt;IMySecureService&gt;.CreateChannel(binding, address); string result = serviceProxy.GetData(123); ``` 至此,我们已经成功地创建了一个使用WCF和HTTPS的C#服务...

    WCF系列学习源码

    `WCF_序列化`与`WCF_序列化下`这两个文件着重展示了如何使用.NET内置的XML序列化器和数据契约序列化器进行数据转换。同时,它们也演示了如何自定义数据契约以满足特定需求,以及如何处理序列化时的异常。 3. **WCF...

    WCF全面解析上下册包含全部源码

    《WCF全面解析》上下册是一套深入探讨Windows Communication Foundation(WCF)技术的专业书籍,包含完整的源码供读者实践和学习。WCF是微软.NET Framework中的一个关键组件,用于构建分布式应用程序,它集成了多种...

    WCF教程WCF教程

    ### 第三部分:WCF高级主题 深入学习WCF的高级特性: 1. **安全性**:包括身份验证、授权、加密和消息完整性的实现。 2. **事务**:在分布式环境中支持原子性、一致性、隔离性和持久性的事务管理。 3. **可靠消息...

    wcf服务编程第三版源代码

    **WCF服务编程第三版源代码详解** Windows Communication Foundation(WCF)是.NET框架中用于构建分布式应用程序的服务模型。在《WCF服务编程第三版》一书中,作者深入探讨了如何利用WCF来创建高效、安全且可靠的...

    WCF服务器与客户端使用示例文件v0.2(包含全双工模式和调用web中的wcf服务).zip

    **Windows Communication Foundation (WCF)**是微软提供的一种统一的编程模型,用于构建面向服务的应用程序。它允许服务和客户端之间进行通信,支持多种传输协议、消息格式和绑定类型,包括HTTP、TCP、命名管道等。...

    我的WCF之旅:计算器 WCF样例源代码

    我的WCF之旅- 创建一个简单的WCF程序 - Artech WCF入门之选绝佳的例子 代源源于:《WCF全面解析 上》 编程工具:VS2010 语言:C# blog 《IIS站点中部署 WCF项目》

    WCF技术专题:WCF入门与进阶

    总之,WCF是.NET框架中实现服务导向架构的重要工具,对于理解分布式系统和面向服务的编程模型有着重要的学习价值。通过深入掌握WCF,开发者能够构建高效、安全、可扩展的服务,为企业的IT系统提供坚实的基础。

    WCF监听通信过程程序

    2. **配置日志输出**:在服务行为中,指定日志的详细级别,如`&lt;system.diagnostics&gt;&lt;sources&gt;...&lt;/sources&gt;`,并定义TraceListeners,比如文本文件监听器,将日志写入文件。 3. **客户端配置**:同样地,客户端也...

    我的WCF之旅源代码_创建一个简单的WCF程序

    5. **创建客户端**:使用WCF客户端(Channel Factory或添加服务引用)创建客户端代理,调用服务。客户端配置通常与服务配置相匹配。 6. **调用服务**:通过客户端代理调用服务操作,获取返回结果。 在"创建一个简单...

    WCF 我的WCF之旅示例代码

    在这个“WCF我的WCF之旅示例代码”中,我们可以看到一系列逐步进阶的代码示例,这些示例有助于理解WCF的核心概念和技术。 首先,我们要了解WCF的基本组成部分: 1. **服务**:服务是WCF中的核心元素,它定义了对外...

    SOA模式的轻量级服务调用框架模型 WCF

    **SOA模式的轻量级服务调用框架模型 WCF** **一、SOA(Service-Oriented Architecture)服务导向架构** SOA是一种设计模式,它提倡将业务功能分解为独立的服务,这些服务可以通过标准接口进行交互,实现松耦合和...

Global site tag (gtag.js) - Google Analytics