跟我一起學WCF(9)——WCF回調操作的實現


一、引言

  在上一篇文章中介紹了WCF對Session的支持,在這篇文章中將詳細介紹WCF支持的操作。在WCF中,除了支持經典的請求/應答模式外,還提供了對單向操作、雙向回調操作模式的支持,此外還有流操作的支持。接下來將詳細介紹下這幾種操作,並實現一個雙向回調操作的例子。

二、WCF操作詳解

2.1 請求—應答操作

   請求應答模式是WCF中默認的操作模式。請求應答模式指的是:客戶端以消息形式發送請求,它會阻塞客戶端直到收到應答消息。應答的默認超時時間為1分鍾,如果超過這一時間服務仍然沒有應答,客戶端就會獲得一個TimeOutException異常。WCF中除了NetPeerTcpBinding和NetMsmqBinding綁定,所有的綁定都支持請求—應答操作。

2.2 單向操作

   單向操作是沒有返回值的,客戶端不關心調用是否成功。單向操作指的是:客戶端一旦發出調用請求,WCF會生成一個請求消息發送給服務端,但客戶端並不需要接收相關的應答消息。因此,單向操作不能有返回值,並且服務端拋出的任何異常都不會傳遞給客戶端。所以客戶端如果需要捕獲服務端發生的異常,此時不能把操作契約的IsOneWay屬性設置為true,該屬性的默認值為false。異常處理參考:如何在WCF進行Exception Handling。單向操作不等同於異步操作,單向操作只是在發出調用的瞬間阻塞客戶端,但如果發出多個單向調用,WCF會將請求調用放入服務端的隊列中,並在某個時間進行執行。隊列的存儲個數有限,一旦發出的調用個數超出了隊列容量,則會發生阻塞現象,此時調用請求無法放入丁烈,直到有其他請求被處理,即隊列中的請求出隊列后,產生阻塞的調用就會放入隊列,並解除對客戶端的阻塞。WCF中所有綁定都支持單向操作。WCF中實現單向操作只需要設置IsOneWay屬性為true即可。這里需要注意一點:由於單向操作沒有應答消息,因此它不能包含返回結果。

2.3 回調操作

   WCF支持服務將調用返回給它的客戶端。在回調期間,服務成為了客戶端,而客戶端成為了服務。在WCF中,並不是所有的綁定都支持回調操作,只有具有雙向能力的綁定才能夠用於回調。例如,HTTP本質上是與連接無關的,所以它不能用於回調,因此我們不能基於basicHttpBinding和wsHttpBinding綁定使用回調,WCF為NetTcpBinding和NetNamedPipeBinding提供了對回調的支持,因為TCP和IPC協議都支持雙向通信。為了讓Http支持回調,WCF提供了WsDualHttpBinding綁定,它實際上設置了兩個Http通道:一個用於從客戶端到服務的調用,另一個用於服務到客戶端的調用。

  回調操作時通過回調契約來實現的,回調契約屬於服務契約的一部分,一個服務契約最多只能包含一個回調契約。一旦定義了回調契約,就需要客戶端實現回調契約。在WCF中,可以通過ServiceContract的CallbackContract屬性來定義回調契約。具體的實現代碼如下所示:

// 指定回調契約為ICallback
    [ServiceContract(Namespace="http://cnblog.com/zhili/", CallbackContract=typeof(ICallback))] 
    public interface ICalculator
    {
        [OperationContract(IsOneWay = true)]
        void Multiple(double a, double b);
    }

// 回調契約的定義,此時回調契約不需要應用ServiceContractAttribute特性
    public interface ICallback
    {
        [OperationContract(IsOneWay = true)]
        void DisplayResult(double x, double y, double result);
    }

  在上面代碼中,回調契約不必標記ServiceContract特性,因為類型只要被定義為回調契約,就代表它具有ServiceContract特性,但仍然需要為所有的回調接口中的方法標記OperationContract特性。

2.4 流操作

  在默認情況下,當客戶端與服務交換消息時,這些消息會被放入到接收端的緩存中,一旦接收到完整的消息,就立即被傳遞處理。無論是客戶端發送消息到服務還是服務返回消息給客戶端,都是如此。當客戶端調用服務時,只要接收到完整的消息,服務就會被調用,當包含了調用結果的返回消息被客戶端完整接收時,才會接觸對客戶端的阻塞。對於數據量小的消息,這種交換模式提供了簡單的編程模型,因為接收消息的耗時較短,然而,一旦處理數據量更大的消息,例如包含了多媒體內容或大文件,如果每次都要等到完整地接收消息之后才能解除阻塞,這未免也不現實。為了解決這樣的問題,WCF允許接收端通過通道接收消息的同時,啟動對消息數據的處理,這樣的處理過程稱為流傳輸模型。對於具有大量負載的消息而言,流操作改善了系統的吞吐量和響應速度,因為在發生和接收消息的同時,不管是發送端還是接收端都不會被阻塞。

三、WCF中回調操作的實現

   上面介紹了WCF中支持的四種操作,下面就具體看看WCF中回調操作的實現。該例子的基本原理是:客戶端調用服務操作,服務操作通過客戶端上下文實例調用客戶端操作。下面還是按照三個步驟來實現該WCF程序。

  第一步:同樣是實現WCF服務契約和契約的實現。具體的實現代碼如下所示:

 1 // 指定回調契約為ICallback
 2     [ServiceContract(Namespace="http://cnblog.com/zhili/", CallbackContract=typeof(ICallback))] 
 3     public interface ICalculator
 4     {
 5         [OperationContract(IsOneWay = true)]
 6         void Multiple(double a, double b);
 7     }
 8 
 9  // 回調契約的定義,此時回調契約不需要應用ServiceContractAttribute特性
10     public interface ICallback
11     {
12         [OperationContract(IsOneWay = true)]
13         void DisplayResult(double x, double y, double result);
14     }
15 
16  // 服務契約的實現
17     public class CalculatorService : ICalculator
18     {
19         #region ICalculator Members
20         public void Multiple(double a, double b)
21         {
22             double result = a * b;
23             // 通過客戶端實例通道
24             ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>();
25 
26             // 對客戶端操作進行回調
27             callback.DisplayResult(a, b, result);
28         }
29         #endregion
30     }

  第二步:實現服務宿主。這里還是以控制台程序作為服務宿主。具體的實現代碼如下所示:

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
 6             {
 7                 host.Opened += delegate
 8                 {
 9                     Console.WriteLine("Service start now....");
10                 };
11 
12                 host.Open();
13                 Console.Read();
14             }
15         }
16     }

  宿主對應的配置文件內容如下所示:

<configuration>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior>
                    <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8080/Metadata"/>
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <services>
            <service name="WCFContractAndService.CalculatorService">
                <endpoint address="net.tcp://localhost:9003/CalculatorService" binding="netTcpBinding" contract="WCFContractAndService.ICalculator"/>
            </service>
        </services>
    </system.serviceModel>
</configuration>

  第三步:實現客戶端。由於服務端來對客戶端操作進行回調,所以此時客戶端需要實現回調契約。首先以管理員權限啟動服務宿主,服務宿主啟動成功之后,客戶端通過添加服務引用的方式來生成客戶端代理類,此時需要在添加服務引用窗口地址中輸入:http://localhost:8080/Metadata。添加服務引用成功之后,接着在客戶端實現回調契約,具體的實現代碼如下所示:

1 // 客戶端中對回調契約的實現
2     public class CallbackWCFService : ICalculatorCallback
3     {
4         public void DisplayResult(double a, double b, double result)
5         {
6             Console.WriteLine("{0} * {1} = {2}", a, b, result);
7         }
8     }

  接下來就是實現測試回調操作的客戶端代碼了。具體的實現步驟是:實例化一個回調類的實例,然后把它作為上下文實例的操作,最后把上下文實例作為客戶端代理的參數來實例化客戶端代理。具體的實現代碼如下所示:

 1  // 客戶端實現,測試回調操作
 2     class Program
 3     {
 4         static void Main(string[] args)
 5         {
 6             InstanceContext instanceContex = new InstanceContext(new CallbackWCFService());
 7             CalculatorClient proxy = new CalculatorClient(instanceContex);
 8             proxy.Multiple(2,3);
 9 
10             Console.Read();
11         }
12     }

  下面運行運行該程序來檢測下該程序是否能夠成功回調,首先以管理員權限啟動服務宿主程序,再啟動客戶端程序,如果回調成功,你將看到如下圖所示的運行結果:

  這里只是演示了回調操作的實現,關於流操作的實現,這里就不再去實現了,等具體需要的時候再去研究吧,同時給出關於流操作實現的參考文章:

  Stream Operation in WCF

      WCF流處理(Streaming)機制

四、總結

  到這里,WCF操作的內容就分享結束了,本文首先介紹了在WCF中支持四種操作:請求-應答操作、單向操作、回調操作和流操作,WCF中默認的操作時請求-應答操作,最后實現了一個回調操作的實例。

  本文所有源碼:WCFCallbackOperation.zip

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM