WCF后传系列(7):消息如何传递之绑定Part 2

概述

每个服务终结点都包含一个地址Address、一个绑定Binding 和一个契约Contract。契约指定可用的操作,绑定指定如何与服务进行通信,而地址指定查找服务的位置,在WCF专题系列前5篇中,深入了解了WCF中寻址的细节。本文为消息如何传递之绑定第二部分,将详细介绍WCF内置的各种绑定元素,绑定元素之间的顺序以及如何创建一个自定义的绑定元素。

WCF专题系列(6):消息如何传递之绑定Part 1一文中,我提到绑定由绑定元素组成,每个绑定元素用来描述终结点与客户端通信方式中的某个方面,在发送或接收消息时,每个绑定元素都表示一个处理步骤;运行时,绑定元素会创建必要的通道和侦听器,用以生成传出和传入通道堆栈,其中三种主要的绑定元素是协议绑定元素,编码绑定元素以及传输绑定元素,下面再对它们重新认识一下。

协议绑定元素

这些元素表示对消息执行的更高级别的处理步骤,如可靠性、安全性、事务等处理,由这些绑定元素创建的通道和侦听器可以添加、移除或修改消息内容,以符合WS-*系列规范,给定的绑定可以具有0或多个协议绑定元素,WCF中内置的几种协议绑定元素,其中包括:

1.ReliableSessionBindingElement:该绑定元素会在堆栈中提供一个可选层,该可选层可在终结点之间建立可靠会话并配置此会话的行为。所谓的可靠性,是指SOAP消息可以在不可靠的网络上(如HTTP)进行可靠的传递,保证消息无重复的、消息次序正确的进行交换,它的原理是:为一组消息设定相同的ID,根据消息号将消息编组,并根据顺序号进行排序,大家可以参考WS-Reliability和WS-ReliableMessaging协议。它的定义如下所示:

public sealed class ReliableSessionBindingElement
    : BindingElement, IPolicyExportExtension
{
    public bool Ordered { get; set; }

    public ReliableMessagingVersion ReliableMessagingVersion { get; set; }

    // 更多成员
}

WCF中内置的几个绑定已经包含了ReliableSessionBindingElement,如果要添加该元素到其它绑定上,可以使用如下配置:

<bindings>
  <customBinding>
    <binding name="reliabilityhttp">
      <reliableSession/>
    </binding>
  </customBinding>
</bindings>

2.SecurityBindingElement:该绑定元素为WCF中SOAP消息安全绑定元素的基类,它有三种具体的实现:支持对称加密通道安全的SymmetricSecurityBindingElement、支持不对称加密通道安全的AsymmetricSecurityBindingElement 和 支持混合模式通道安全的TransportSecurityBindingElement,如下图所示:

TerryLee_WCF_21

这些实现为在WS-Security Policy规范中定义的绑定建模,在创建自定义绑定中,我们需要提供SecurityBindingElement的某一个具体的实现,或者自定义一个类从SecurityBindingElement继承。

3. TransactionFlowBindingElement:该绑定元素允许在终结点绑定设置中启用或禁用传入事务流,并允许指定传入事务所需的协议格式。它的定义如下所示:

public sealed class TransactionFlowBindingElement
    : BindingElement, IPolicyExportExtension
{
    public TransactionProtocol TransactionProtocol { get; set; }

    // 更多成员
}

在补充的Web服务规范中,有一系列的关于事务处理的规范,如WS-AtomicTransactions、WS-Coordination等等。

编码绑定元素

所谓的编码是将消息转换为一个字节序列的过程,而解码是相反的过程。编码绑定元素表示消息与准备用于网络传输的编码之间的转换,典型的WCF绑定正好包括一个编码绑定元素。WCF内置的编码绑定元素包括 MtomMessageEncodingBindingElement、BinaryMessageEncodingBindingElement 和 TextMessageEncodingBindingElement。 如果未对绑定指定编码绑定元素,则使用默认的编码。当传输协议是HTTP时,默认编码为文本,对于其他传输协议,默认编码为二进制。如下图所示:

TerryLee_WCF_22

1. TextMessageEncodingBindingElement:表示文本方式编码的XML消息编码器,它的优点是互操作性最强,缺点是效率最低。WCF服务或者客户端通常可以理解文本XML。但是,将大型二进制数据块作为文本传输不是有效的传输方式,它的定义如下所示:

public sealed class TextMessageEncodingBindingElement
    : MessageEncodingBindingElement, IWsdlExportExtension, IPolicyExportExtension
{
    public int MaxReadPoolSize { get; set; }

    public int MaxWritePoolSize { get; set; }

    public override MessageVersion MessageVersion { get; set; }

    public Encoding WriteEncoding { get; set; }

    public override MessageEncoderFactory CreateMessageEncoderFactory();

    // 更多成员
}

2.BinaryMessageEncodingBindingElement是指定在编码消息时应该使用二进制XML格式的绑定元素,它包含用于指定要使用何种字符编码以及SOAP消息与 WS-Addressing版本的选项。二进制编码的优点是效率最高,缺点是互操作性最低,它的定义如下所示:

public sealed class BinaryMessageEncodingBindingElement
    : MessageEncodingBindingElement,
    IWsdlExportExtension, IPolicyExportExtension
{
    public int MaxReadPoolSize { get; set; }

    public int MaxSessionSize { get; set; }

    public int MaxWritePoolSize { get; set; }

    public override MessageVersion MessageVersion { get; set; }

    public override MessageEncoderFactory CreateMessageEncoderFactory();

    // 更多成员
}

3.MtomMessageEncodingBindingElement表示指定使用消息传输优化机制 (MTOM) 编码的消息所用的字符编码和消息版本管理以及其他设置的绑定元素。(MTOM) 是WCF消息中传输二进制数据的有效技术。MTOM 编码器会尝试在效率和互操作性之间建立平衡。MTOM 编码以文本形式传输大多数 XML,但通过按原样传输来优化大型二进制数据块的传输,无需将其转换为base64编码格式。它的定义如下所示:

public sealed class MtomMessageEncodingBindingElement
    : MessageEncodingBindingElement,
    IWsdlExportExtension, IPolicyExportExtension
{
    public int MaxBufferSize { get; set; }

    public int MaxReadPoolSize { get; set; }

    public int MaxWritePoolSize { get; set; }

    public override MessageVersion MessageVersion { get; set; }

    public Encoding WriteEncoding { get; set; }

    public override MessageEncoderFactory CreateMessageEncoderFactory();

    // 更多成员
}

如果以上编码不能满足实际的开发需求,我们还可以定义自己的消息编码器,在后面的文章中,我将会详细介绍。

传输绑定元素

这些元素表示传输协议上编码消息的传输。典型的WCF绑定正好包括一个从 TransportBindingElement 继承的传输绑定元素。WCF中内置的传输绑定元素有如下几种:

TcpTransportBindingElement 

HttpTransportBindingElement 

HttpsTransportBindingElement 

NamedPipeTransportBindingElement 

PeerTransportBindingElement 

MsmqTransportBindingElement 

MsmqIntegrationBindingElement 

ConnectionOrientedTransportBindingElement

除此之外,还可以用户自定义的传输绑定元素。

绑定元素顺序

在创建绑定时,向绑定中添加绑定元素的顺序非常重要,必须按照如下顺序进行:

1.最顶层是一个允许流事务的TransactionFlowBindingElement元素,可选;

2.接下来是一个可靠性支持的ReliableSessionBindingElement元素,可选;

3.接下来是一个安全性支持的SecurityBindingElement元素,可选;

4.在接下来是消息编码绑定元素,可以是系统内置的三种消息编码器之一或者自定义的消息编码器,必须具有,但是如果不添加,系统会根据传输不同默认添加一个消息编码器;

5.最底层是一个传输绑定元素,可以是系统内置的几种传输绑定元素之一或者自定义的传输绑定元素。

6.如果是自定义的绑定元素,根据绑定元素的功能可以放在以上几层任意层之间。

如下面的示例代码,创建一个自定义的绑定,并向其中添加三个绑定元素:

// 可靠性支持
ReliableSessionBindingElement reliable =
    new ReliableSessionBindingElement();
reliable.Ordered = false;

// 编码元素
TextMessageEncodingBindingElement text =
    new TextMessageEncodingBindingElement();
text.MessageVersion = MessageVersion.Soap11WSAddressingAugust2004;

// 传输元素
HttpTransportBindingElement http = new HttpTransportBindingElement();
http.TransferMode = TransferMode.Streamed;
http.UseDefaultWebProxy = true;

// 自定义绑定
CustomBinding httpBinding = new CustomBinding();
httpBinding.Name = "httpBinding";
httpBinding.Elements.Add(reliable);
httpBinding.Elements.Add(text);
httpBinding.Elements.Add(http);

host.AddServiceEndpoint(typeof(ICalculator), httpBinding,
    "http://localhost:8887/Calculator");

自定义绑定元素

当在构造一个新的绑定时,如果系统内置的绑定元素无法满足需要,可以开发一个自定义的绑定元素,如自定义的消息绑定元素、自定义的传输绑定元素或者任意一个绑定元素。关于消息绑定元素的自定义,我将在后面消息编码器一文中进行介绍,而自定义传输绑定元素,也是一个相当负责工作,需要创建相应的自定义通道组件,所以将会放在介绍完WCF中通道模型之后再详细讲解。总的来说,实现一个自定义的绑定元素,需要继承于抽象的基类BindingElement,如下面的代码片段:

public class LoggingBindingElement : BindingElement
{
    public LoggingBindingElement()
    {

    }

    public LoggingBindingElement(LoggingBindingElement other)
        : base(other)
    {

    }
    public override BindingElement Clone()
    {
        return new LoggingBindingElement(this);
    }

    public override T GetProperty<T>(BindingContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        return context.GetInnerProperty<T>();
    }
}

在后面的文章将会看到一个完整的自定义绑定元素的例子。

总结

本文为消息如何传递之绑定第二部分,详细介绍了WCF内置的各种绑定元素,绑定元素之间的顺序以及如何创建一个自定义的绑定元素。

posted @ 2008-11-06 23:56 TerryLee 阅读(...) 评论(...) 编辑 收藏