引言

从本质上说,WCF是一个通信服务框架,它允许我们使用不同的传输协议,使用不同的消息编码形式,跟不同的WS-*系列规范交互,而所有这些细节都是由通道堆栈来处理的。为了简化这些处理,在WCF中提供了两种模型,一是针对开发者的应用程序编程模型;二是用来通信的通道模型,这样对于开发者来说,只要了解应用程序编程模型就足够了,而不会涉及到通道模型,然而,对于通道模型进行必要的学习,可以让我们真正理解WCF中“通信”概念,了解WCF的 整个架构体系,从而构建出更加健壮的WCF服务或者对WCF框架进行扩展。在本文中,我们将进行深度了解WCF中的通道模型是如何设计的。

通道模型概述

在WCF中,提供了一系列的接口和其它类型模型,它们为消息的发送和接收提供了一个底层的编程模型,该模型称之为WCF通道模型。在通道模型中,一个很重要的概念是通道堆栈,它是具有一个或多个消息处理通道的分层的通信堆栈,堆栈中放置了各种类型的通道,用来对象进行处理,如在通道堆栈的最底层放置了传输通道,它负责使通道堆栈适应基础传输,如图1所示:
TerryLee_WCF_23
图1
在通道堆栈中,不仅仅提供消息的传输方式,还提供了其它诸如对消息的内容或者消息头进行处理的功能,这些功能同样是以通道的方式放置在通道堆栈中,甚至于我们可以编写自己的通道,加入到通道堆栈中。
消息在通道堆栈中传输时,将作为Message对象流过通信堆栈,如传输通道负责在发送方和接收方之间转换消息,之后消息将通过传输通道继续往上流,依次经过通道堆栈中的各个通道,这些通道各自负责提供一种通信功能,如在消息头中添加信息,对消息的正文进行加密等等。

通道对象模型

通道对象模型是实现通道、通道侦听器和通道工厂所必需的一组核心接口。还提供一些基类以辅助自定义实现。可以看到通道模型中最重要的有三组接口:通道、通道侦听器和通道工厂。每个通道均实现一个或多个接口,称为通道形状接口或通道形状;通道侦听器负责侦听传入消息,即在消息的接收端,然后通过由通道侦听器创建的通道将这些消息传送到上面的层;通道工厂负责创建通道用于发送消息,即在消息的发送方,并在通道工厂关闭时,关闭通道工厂创建的所有通道。
在通道模型中,最重要的一个接口是ICommunicationObject,它定义了所有通信对象实现的基本状态机的核心接口,自定义通道通信对象可以直接实现ICommunicationObject,如图2所示:
TerryLee_WCF_24
图2
只有图2中的这些接口,才属于WCF的通道模型,在WCF中同样提供了一些基类如CommunicationObject、ChannelFactoryBase等,在实现自定义的通道通信对象时,也可以直接继承于这些基类,但要注意,这些基类仅仅是为实现自定义通道通信对象提供了方便,它们本身并不属于通道模型的一部分。
ICommunicationObject接口为WCF中所有面向通信的对象提供了契约,除了通道、通道侦听器、通道工厂外,还有调度程序和服务主机,定义了基本状态的协定。它包括一组用于启动状态转换的打开、关闭和中止方法,打开和关闭方法的异步版本,一组提供状态转换通知的事件和一个个用于检查对象状态的公开State属性,它的定义如下所示:
public interface ICommunicationObject
{
    // 状态属性
    CommunicationState State { get; }
    // 事件
    event EventHandler Closed;
    event EventHandler Closing;
    event EventHandler Faulted;
    event EventHandler Opened;
    event EventHandler Opening;
    // 方法
    void Abort();
    void Close();
    void Close(TimeSpan timeout);
    void Open();
    void Open(TimeSpan timeout);
    // 异步方法
    IAsyncResult BeginClose(AsyncCallback callback, object state);
    IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state);
    IAsyncResult BeginOpen(AsyncCallback callback, object state);
    IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state);
    void EndClose(IAsyncResult result);
    void EndOpen(IAsyncResult result);
}
ICommunicationObject 的初始状态是“已创建”,此时可以配置它的各种属性。 一旦处于“已打开”状态,对象就可用于发送和接收消息,但它的属性将视为不可变。 一旦处在“正在关闭”状态,对象就不能再处理新的发送或接收请求,但在到达“关闭”超时前有可能完成现有的请求。 如果发生不可恢复的错误,则对象将转换到“出错”状态,此时可以检查该对象以获取有关错误的信息,该对象最终将关闭。 处于“已关闭”状态时,该对象实质上已到达状态机的终点。 对象一旦从一个状态转换到下一个状态,它将不会返回至前一状态,整个过程图3所示:
TerryLee_WCF_30
图 3

通道形状

每个通道均实现一个或多个接口,称为通道形状接口或通道形状。通道形状的最底层是 IChannel 接口,该接口提供一个 GetProperty<T> 方法,用作访问由通道堆栈中的通道公开的任意功能的分层机制。扩展 IChannel 的五种通道形状为:
1.IInputChannel:用于接收消息
2.IOutputChannel:用于发送消息
3.IRequestChannel:用于发送请求
4.IReplyChannel:用于发送回复
5.IDuplexChannel:用于双向消息传递
它们之间的关系如图4所示:
TerryLee_WCF_25
图 4
其实可以看出,IDuplexChannel接口是IInputChannel和IOutputChannel接口的联合,所有的通道形状都同时扩展了ICommunicationObject和IChannel。这5种通道模型分别对应于不同的消息交换模式,在使用数据报模式时,消息发送方通道实现了IOutputChannel接口,而消息接收方通道实现了IInputChannel接口;在请求响应模式中,客户端通道实现IRequestChannel接口,而服务通道实现IReplyChannel接口;在双工通信模式中,由于双方都能发送和接收消息,客户端和服务通道实现了IDuplexChannel接口,如图5所示:
TerryLee_WCF_29
图 5

服务端通道

在通道对象模型中,除了IChannel接口,另外一个接口IChannelListener用于消息的接收端,通过绑定来生成通道侦听器(在绑定中有关于协议、编码和传输的信息,关于绑定可以参考 WCF专题系列(6):消息如何传递之绑定Part 1),用于侦听传入的消息。通道侦听器负责创建通道并从下面的层或者从网络接收消息,收到的消息将借助于通道侦听器所创建的通道传送到上面的层中。整个过程如图6所示:
TerryLee_WCF_26
图 6
在WCF的内部,对于消息的每一个处理(即通道堆栈中的通道),都会对应一个内部的通道侦听器,如针对事务处理的TransactionChannelListener和使用TCP传输的TcpChannelListener,分别用于创建各自对应的通道。

客户端通道

在WCF的客户端,通道的创建使用通道工厂,创建的这些通道负责获取来自上一层的消息,对消息进行必要的处理,然后将消息发送到下一层,如图7所示:
TerryLee_WCF_27
图 7
在WCF内部,同样对于消息的每一个处理,都会有相应的通道工厂,如使用TCP传输的TcpChannelFactory,用于创建对应的通道。

总结

本文详细介绍了WCF中的通道编程模型以及关于通道、通道监听器和通道工厂等,大多数都是纯理论的知识,在下一篇文章中,将会通过一个示例来加深对于本文所讲知识的认识。

0

收藏

lihuijun

203篇文章,69W+人气,0粉丝

Ctrl+Enter 发布

发布

取消

推荐专栏更多

5353379fc95da1d7d34fd243b9ace17f.jpg
全局视角看大型园区网

路由交换+安全+无线+优化+运维

共40章 | 51CTO夏杰
¥51.00 1666人订阅
45862f289339dc922ffda669fd74ad9b.jpg
网工2.0晋级攻略 ——零基础入门Python/Ansible

网络工程师2.0进阶指南

共30章 | 姜汁啤酒
¥51.00 1566人订阅
a940c66317ecbe58436a2ad3831c2d7d.png
基于Python的DevOps实战

自动化运维开发新概念

共20章 | 抚琴煮酒
¥51.00 430人订阅
629650e188ddde78b213e564c2e9ebff.jpg
负载均衡高手炼成记

高并发架构之路

共15章 | sery
¥51.00 507人订阅
dc6736c5fd50474b5df8b76b040e3d03.jpg
带你玩转高可用

前百度高级工程师的架构高可用实战

共15章 | 曹林华
¥51.00 462人订阅
f92360e227f9d91cdff7ea95120630ef.png
left-qr.jpg

扫一扫,领取大礼包

0

分享
qr-url?url=https%3A%2F%2Fblog.51cto.com%2Fterrylee%2F151970
lihuijun
noavatar_middle.gif