Mono 3.0.2 基於雙工通訊的WCF應用 Demo

weixin_34344677發表於2012-12-30

雙工(Duplex)模式的訊息交換方式體現在訊息交換過程中,參與的雙方均可以向對方傳送訊息。基於雙工MEP訊息交換可以看成是多個基本模式下(比如請求-回覆模式和單項模式)訊息交換的組合。雙工MEP又具有一些變體,比如典型的訂閱-釋出模式就可以看成是雙工模式的一種表現形式。雙工訊息交換模式使服務端回撥(Callback)客戶端操作成為可能。本文測試Mono 3.0.2/.NET 4對雙工(Duplex)模式的WCF支援。

演示基於雙工通訊的WCF應用是一個簡單的計算服務CalculatorService,我們通過單向(One-way)的模式呼叫CalculuateService(也就是客戶端不可能通過回覆訊息得到計算結果),服務端在完成運算結果後,通過回撥(Callback)的方式在客戶端將計算結果列印出來。

image

步驟一:定義服務契約和回撥契約

首先進行服務契約的定義,我們照例通過介面(ICalculator)的方式定義服務契約,作用於指定加法運算的Add操作,我們通過OperationContractAttribute特性的IsOneway屬性將操作定義成單向的操作,這意味著客戶端僅僅是向服務端傳送一個運算的請求,並不會通過回覆訊息得到任何運算結果。

image

通過在服務端回撥客戶端操作的方式實現運算結果的輸出。客戶端呼叫CalculatorService正常的服務呼叫,那麼在服務執行過程中藉助於客戶端在服務呼叫時提供的回撥物件對客戶端的操作進行回撥,從本質上講是另外一種形式的服務呼叫。WCF採用基於服務契約的呼叫形式,客戶端正常的服務呼叫需要服務契約,同理服務端回撥客戶端依然需要通過描述回撥操作的服務契約,我們把這種服務契約稱為回撥契約。回撥契約的型別通過ServiceContractAttribute特性的CallbackContract屬性進行指定。

上面程式碼中服務契約ICalculator的回撥契約ICallback定義如下。由於回撥契約本質也是一個服務契約,所以定義方式和一般意義上的服務契約基本一樣。ICallback定義了一個服務操作DisplayResult用於顯示運算結果(前兩個引數為執行加法運算的運算元),由於服務端不需要回撥的返回值,索性將回撥操作也設為單向方法。

image

步驟二:實現服務

在實現了上面定義的服務契約ICalculator的服務CalculatorService中,實現了Add操作,完成運算和結果顯示的工作。結果顯示是通過回撥的方式實現的,所以需要藉助於客戶端提供的回撥物件(該物件在客戶端呼叫CalculatorService的時候指定,在介紹客戶端程式碼的實現的時候會講到)。在WCF中,回撥物件通過當前OperationContext的GetCallback<T>方法獲得(T代表回撥契約的型別)。

image

OperationContext在WCF中是一個非常重要、也是一個十分有用的物件,它代表服務操作執行的上下文。我們可以通過靜態屬性Current(OperationContext.Current)得到當前的OperationContext。藉助OperationContext,我們可以在服務端或者客戶端獲取或設定一些上下文,比如在客戶端可以通過它為出棧訊息(outgoing message)新增SOAP報頭,以及HTTP報頭(比如Cookie)等。在服務端,則可以通過OperationContex獲取在客戶端設定的SOAP報頭和HTTP報頭。

步驟三:服務寄宿

我們通過一個控制檯應用程式完成對CalculatorService的寄宿工作,並將所有的服務寄宿的引數定義在配置檔案中。由於雙工通訊依賴於一個雙工的通道棧,即依賴於一個能夠支援雙工通訊的繫結,在此我們選用了NetTcpBinding,Mono下的wsDualHttpBinding 是不支援的哦,具體可以參看 http://www.mono-project.com/WCF_Development

<?xml version="1.0"?>
<configuration>
    <system.serviceModel>
        <services>
            <service name="DuplexWCF.Service.CalculatorService" behaviorConfiguration="duplexWcf">
                <endpoint address="net.tcp://192.168.10.96:9999/calculator" binding="netTcpBinding"  bindingConfiguration="duplexnetTcpBinding" 
                  contract="DuplexWCF.Contract.ICalculator"/>
            </service>
        </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="duplexWcf">
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

  <bindings>
     <netTcpBinding>
       <binding name = "duplexnetTcpBinding">
         <security mode ="None" />
       </binding>
     </netTcpBinding>
   </bindings>

  </system.serviceModel>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
注: 在WCF預定義繫結型別中,WSDualHttpBindingNetTcpBinding均提供了對雙工通訊的支援,但是兩者在對雙工通訊的實現機制上卻有本質的區別。WSDualHttpBinding是基於HTTP傳輸協議的;而HTTP協議本身是基於請求-回覆的傳輸協議,基於HTTP的通道本質上都是單向的。WSDualHttpBinding實際上建立了兩個通道,一個用於客戶端向服務端的通訊,而另一個則用於服務端到客戶端的通訊,從而間接地提供了雙工通訊的實現。而NetTcpBinding完全基於支援雙工通訊的TCP協議。

配置裡頭<endpoint address="net.tcp://192.168.10.96:9999/calculator" 使用localhost代替具體的ip時候出現無法連線的情況。

image

MONO_STRICT_MS_COMPLIANT 這個環境變數也不需要了哈,完全原生的Linux支援了哦,之前有網友碰到過WCF的相容性問題是通過設定環境變數來相容.NET的。具體可以參看

步驟四:實現回撥契約

在客戶端程式為回撥契約提供實現,在下面的程式碼中CalculateCallback實現了回撥契約ICallback,在DisplayResult方法中對運算結果進行輸出。

image

步驟五:服務呼叫

接下來實現對雙工服務的呼叫,下面是相關的配置和託管程式。在服務呼叫程式中,通過DuplexChannelFactory<TChannel>建立服務代理物件,DuplexChannelFactory<TChannel>和ChannelFactory<TChannel>的功能都是一個服務代理物件的建立工廠,不過DuplexChannelFactory<TChannel>專門用於基於雙工通訊的服務代理的建立。在建立DuplexChannelFactory<TChannel>之前,先建立回撥物件,並通過InstanceContext對回撥物件進行包裝。

image

image

在服務寄宿程式啟用的情況下,執行客戶端程式後,通過服務端執行的運算結果會通過回撥客戶端的操作顯示出來,下面是最終輸出的結果。

XX`V)W}~V7{K6P6LZJDUJ]J

程式碼下載

相關文章:

我的WCF之旅(3):在WCF中實現雙工通訊

Mono WCF Advent Day 11: NetTcpBinding

Using WCF Callback Services Throttling

相關文章