WCF後傳系列(6):消息如何傳遞之綁定Part 1

概述

每一個服務終結點都包含一個地址Address、一個綁定Binding 和一個契約Contract。契約指定可用的操做,綁定指定如何與服務進行通訊,而地址指定查×××的位置,在WCF專題系列前5篇中,深刻了解了WCF中尋址的細節;從本文開始,將深刻了解經典「ABC」中的B,即綁定Binding,瞭解它的原理,如何使用綁定通訊以及在元數據中如何公開

什麼是綁定

從本質上說,WCF是一個通訊服務框架,它容許咱們使用不一樣的傳輸協議(如Http、Https、TCP、P2P、IPC和MSMQ等),使用不一樣的消息編碼形式(文本、二進制和MTOM),跟不一樣的WS-*系列規範(如WS-Security、WS-Atomic Transaction等)交互。全部這些細節都是由通道堆棧來處理的,看一下Aaron Skonnard給出的這幅圖:
TerryLee_WCF_19
圖1
最底層傳輸組件讀入消息,消息編碼器將傳入字節讀取爲邏輯消息對象,以後消息經過通道堆棧中的各個消息,它們執行各自的處理。若是對這三者之間之間進行組合,至少能夠獲得上千種不一樣的通訊方式,可是這些傳輸、編碼以及協議之間有些是互斥的,有些相互約束,也就是說,對於開發人員來講,每構建一個服務,都要須要考慮這三者之間是否能夠共存,是不是高效的通訊方式,顯然這個工做是很是複雜的,要求開發者必須瞭解全部的傳輸、編碼以及協議等。
爲了簡化這三者之間的管理,WCF中引入了綁定的概念(Binding),每一個綁定中都封裝了傳輸協議、消息編碼和多種協議的集合,這樣在構建服務時,咱們就能夠直接選擇一個適用的綁定,經過調整它們的屬性來適應需求,若是系統內置的綁定經過調整屬性仍然不能達到咱們的要求,這時纔會考慮自定義綁定。這樣,經過綁定,就把應用程序編程模型與通道模型(後面會有專門的文章寫到)關聯了起來,對於開發者來講,就無需再考慮複雜的底層通道模型,直接使用應用程序編程模型。

綁定元素

在WCF中,綁定由綁定元素組成,每一個綁定元素用來描述終結點與客戶端通訊方式中的某個方面,綁定元素繼承於BindingElement,其中最重要的綁定元素有以下三種:
1.編碼綁定元素(Encoding Binding Element):如採用文本、二進制仍是MTOM的方式;
2.傳輸綁定元素(Transport Binding Element):使用Http、TCP或者MSMQ進行傳輸;
3.協議綁定元素(Protocol Binding Element):指定可靠性、安全性、事務等。
每一個綁定必需要有一個編碼綁定元素和一個傳輸綁定元素,以及包括任意數目的其餘協議綁定元素。

通道模型中使用綁定

在WCF中,提供了兩個層面的模型,一是針對開發人員的應用程序編程模型;二是用於通訊的通道模型(後面會專門講到)。在通道模型編程中,服務端偵聽並接收消息的第一步就是建立綁定,以下面的代碼:
// 建立自定義綁定
BindingElement[] bindingElements = new BindingElement[2];
bindingElements[0] = new TextMessageEncodingBindingElement();
bindingElements[1] = new HttpTransportBindingElement();
CustomBinding binding = new CustomBinding(bindingElements);
這裏建立了一個自定義綁定,並在其中加入了兩個必須的綁定元素,消息編碼採用文本的方式,而傳輸綁定元素採用了內置的HttpTransportBindingElement。接下來就可使用自定義的綁定來建立通道偵聽器,並進行消息的偵聽,以下代碼所示:
/// <summary>
/// Author:TerryLee
/// Url:[url]http://www.cnblogs.com/terrylee[/url]
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
    // 建立自定義綁定
    BindingElement[] bindingElements = new BindingElement[2];
    bindingElements[0] = new TextMessageEncodingBindingElement();
    bindingElements[1] = new HttpTransportBindingElement();
    CustomBinding binding = new CustomBinding(bindingElements);
    // 使用自定義綁定建立通道偵聽器         
    IChannelListener<IReplyChannel> listener =
          binding.BuildChannelListener<IReplyChannel>(
             new Uri("http://localhost:8080/ChannelApp"),
             new BindingParameterCollection());
    // 監聽消息
    listener.Open();
    Console.WriteLine("Listening for incoming channel connections");
    IReplyChannel channel = listener.AcceptChannel();
    Console.WriteLine("Channel accepted. Listening for messages");
    channel.Open();
    while (true)
    {
        RequestContext request = channel.ReceiveRequest();
        // 讀取請求的消息
        Message message = request.RequestMessage;
        Console.WriteLine("Message Received");
        Console.WriteLine("Message Action: {0}", message.Headers.Action);
        string body = message.GetBody<string>();
        Console.WriteLine("Message Content: {0}", body);
        // 發送響應消息
        Message replymessage = Message.CreateMessage(
            binding.MessageVersion,
            "http://www.cnblogs.com/terrylee",
             body);
        request.Reply(replymessage);
        // 釋放對象
        message.Close();
        request.Close();
        channel.Close();
        listener.Close();
    }
}
其中的代碼咱們就再也不解釋,到關於WCF中通道編程模型一文中,還會進行詳細的講解。

自定義系統綁定

在WCF中,已經內置了大量的綁定供咱們使用,可是若是這些綁定不能知足實際的開發需求,咱們能夠經過幾種辦法來對系統內置綁定進行自定義,一是經過配置文件進行綁定的配置,以下代碼所示,配置BasicHttpBinding的消息編碼爲MTOM,而安全性爲消息級別:
<services>
  <service name="TerryLee.WCFAddressing.Service.CalculatorService"
           behaviorConfiguration="calculatorBehavior">
    <host>
      <baseAddresses>
        <add baseAddress="[url]http://localhost:8887/Calculator[/url]"/>
      </baseAddresses>
    </host>
    <endpoint address=""
              binding ="basicHttpBinding"
              contract="TerryLee.WCFAddressing.Contract.ICalculator"
              name="defaultBinding"
              bindingConfiguration="myBindingConfiguration">
    </endpoint>
  </service>
</services>
<bindings>
  <basicHttpBinding>
    <binding name="myBindingConfiguration"
             messageEncoding="Mtom">
      <security mode="Message"></security>
    </binding>
  </basicHttpBinding>
</bindings>
二是能夠經過編碼的方式,以下代碼所示:
BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Message.ClientCredentialType = 
    BasicHttpMessageCredentialType.Certificate;
binding.Security.Mode = BasicHttpSecurityMode.Message;
binding.MessageEncoding = WSMessageEncoding.Mtom;
考慮到程序部署以後的修改,仍是推薦使用配置的方式。同時,咱們徹底能夠利用系統內置綁定建立一個自定義的綁定,或者咱們在自定義綁定過程當中,能夠直接經過已有的系統內置綁定來建立一個綁定元素集合,以下代碼所示:
BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Message.ClientCredentialType = 
    BasicHttpMessageCredentialType.Certificate;
binding.Security.Mode = BasicHttpSecurityMode.Message;
binding.MessageEncoding = WSMessageEncoding.Mtom;
CustomBinding mybinding = new CustomBinding(binding);
BindingElementCollection myElements =
    binding.CreateBindingElements();
在下篇文章中,我將會介紹如何徹底從新進行自定義綁定。

元數據中公開綁定

在WCF中,通訊的雙方應該就通訊的細節達成一致,既然綁定中封裝了全部通訊的細節,而服務端惟一公開這些細節的方式就是元數據,因此綁定的相關信息應該經過公開WSDL和 WS-Policy 形式的元數據,這樣服務就能夠和客戶端共享綁定配置,以BasicHttpBinding爲例,它所使用的傳輸是Http,而消息編碼採用文本的方式,若有下面這樣一端配置:
<services>
  <service name="TerryLee.WCFAddressing.Service.CalculatorService"
           behaviorConfiguration="calculatorBehavior">
    <host>
      <baseAddresses>
        <add baseAddress="[url]http://localhost:8887/Calculator[/url]"/>
      </baseAddresses>
    </host>
    <endpoint address="[url]http://localhost:8887/CalculatorService[/url]"
              binding ="basicHttpBinding"
              contract="TerryLee.WCFAddressing.Contract.ICalculator"
              name="defaultBinding"
              bindingConfiguration="myBindingConfiguration">
    </endpoint>
  </service>
</services>
<bindings>
  <basicHttpBinding>
    <binding name="myBindingConfiguration"
             messageEncoding="Mtom">
    </binding>
  </basicHttpBinding>
</bindings>
經過綁定配置,設置BasicHttpBinding的消息編碼爲MTOM,在元數據中,能夠看到採用Http進行傳輸:
<wsdl:binding name="defaultBinding" type="tns:ICalculator">
  <wsp:PolicyReference URI="#defaultBinding_policy" />
  <soap:binding transport="[url]http://schemas.xmlsoap.org/soap/http[/url]" />
  <wsdl:operation name="Add">
    <soap:operation soapAction="[url]http://tempuri.org/ICalculator/Add[/url]"
                    style="document" />
    <wsdl:input>
      <soap:body use="literal" />
    </wsdl:input>
    <wsdl:output>
      <soap:body use="literal" />
    </wsdl:output>
  </wsdl:operation>
</wsdl:binding>
對於消息編碼MTOM,放在Policy的配置中,以下代碼所示:
<wsp:Policy wsu:Id="defaultBinding_policy">
  <wsp:ExactlyOne>
    <wsp:All>
      <wsoma:OptimizedMimeSerialization
        xmlns:wsoma="[url]http://schemas.xmlsoap.org/ws/2004/09/policy/optimizedmimeserialization[/url]" />
    </wsp:All>
  </wsp:ExactlyOne>
</wsp:Policy>

0javascript

收藏css

lihuijun

203篇文章,74W+人氣,0粉絲

Ctrl+Enter 發佈html

發佈java

取消jquery

掃一掃,領取大禮包linux

0git

分享
lihuijun
相關文章
相關標籤/搜索