老老實(shí)實(shí)學(xué)WCF
第七篇 會(huì )話(huà)
通過(guò)前幾篇的學(xué)習,我們已經(jīng)掌握了WCF的最基本的編程模型,我們已經(jīng)可以寫(xiě)出完整的通信了。從這篇開(kāi)始我們要深入地了解這個(gè)模型的高級特性,這些特性用來(lái)保證我們的程序運行的高效、穩定和安全。
首先我們來(lái)學(xué)習會(huì )話(huà)。
1. 什么是會(huì )話(huà)
會(huì )話(huà)是通信雙方進(jìn)行通信的一個(gè)時(shí)間片、一個(gè)語(yǔ)境或者說(shuō)一個(gè)上下文,在這個(gè)特定的環(huán)境中,通信的雙方是彼此認識的,就像兩個(gè)人在聊天,他們都很清楚誰(shuí)在聆聽(tīng)自己講話(huà),也很清楚對方講的話(huà)是給自己聽(tīng)的,簡(jiǎn)單的說(shuō)就是通信雙方是可以記住彼此的。
一旦會(huì )話(huà)結束了,通信雙方就忘記了彼此,即使他們再次建立會(huì )話(huà),他們也不會(huì )記得他們上次會(huì )話(huà)的內容,也就是他們不記得他們曾經(jīng)見(jiàn)過(guò)面。
這在我們現實(shí)世界中或許很難想象,但是在通信的世界里就是這樣的。服務(wù)端不可能記住每個(gè)跟他通信的人,他只能在一段時(shí)間內(會(huì )話(huà))記住一個(gè)人。
這個(gè)特性是很有用的,有些邏輯需要客戶(hù)端和服務(wù)端通信多次才能完成,在這個(gè)期間雙方需要記住彼此,而且會(huì )話(huà)也是很多其他特性實(shí)現的基礎,例如雙工通信。
2. 如何建立會(huì )話(huà)
那么我們要想建立一個(gè)會(huì )話(huà)通信,應該具備怎樣的條件呢?
(1) 需要支持會(huì )話(huà)的綁定。綁定描述了雙方的通信方式,不同的綁定對會(huì )話(huà)的支持是不同的,比如basicHttpBinding是不支持會(huì )話(huà)的,而wsHttpBinding就是支持的。要建立會(huì )話(huà)通信,這個(gè)通信必須首先使用支持會(huì )話(huà)的綁定。
(2) 讓服務(wù)協(xié)定支持會(huì )話(huà),服務(wù)協(xié)定實(shí)際上就是通信的通道(見(jiàn)第四、五篇),讓服務(wù)協(xié)定支持會(huì )話(huà),那么就可以在這個(gè)通信通道上支持會(huì )話(huà)了。
選擇支持會(huì )話(huà)的綁定我們知道怎么做,可如何讓服務(wù)協(xié)定支持會(huì )話(huà)呢?要用到在修飾服務(wù)協(xié)定的SeviceContract屬性,我們知道被這個(gè)屬性修飾的接口是一個(gè)服務(wù)協(xié)定,其實(shí)這個(gè)屬性也擁有屬性,其中一個(gè)屬性叫做SessionMode。這是一個(gè)枚舉,我們通過(guò)設置這個(gè)枚舉的值來(lái)配置服務(wù)協(xié)定是否支持會(huì )話(huà)。例如:
[ServiceContract(SessionMode = SessionMode.Required)] public interface IHelloWCF { [OperationContract] string HelloWCF(); }這段代碼中,我把SessionMode設置為了Required,這表示調用這個(gè)服務(wù)協(xié)定的客戶(hù)端必須使用會(huì )話(huà)。
SessionMode有三個(gè)可能的值:
1) Allowed:這是默認值,表示這個(gè)服務(wù)協(xié)定是允許會(huì )話(huà)的,客戶(hù)端可以選擇用會(huì )話(huà)連接,也可以選擇不用會(huì )話(huà)連接。
2) Required:表示服務(wù)協(xié)定要求客戶(hù)端連接必須使用會(huì )話(huà)。
3) NotAllowed:表示服務(wù)協(xié)定不允許使用會(huì )話(huà)連接。
這些配置需要搭配其他的配置才能起到實(shí)際意義,比如服務(wù)實(shí)例模式,服務(wù)端和客戶(hù)端調用模式等等,等我們了解到這些特性的時(shí)候再展開(kāi),現在我們只需要知道,前兩種配置是支持會(huì )話(huà)的,第三種是不支持的。
3. 一個(gè)簡(jiǎn)單的例子
我們通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)看看允許會(huì )話(huà)與不允許的區別,我修改了前幾篇中寄存在IIS中的服務(wù),代碼如下:
using System;using System.ServiceModel;namespace LearnWCF{ [ServiceContract(SessionMode = SessionMode.Allowed)] public interface IHelloWCF { [OperationContract] string HelloWCF(); } public class HelloWCFService : IHelloWCF { private int _Counter; public string HelloWCF() { _Counter++; return 'Hello, you called ' + _Counter.ToString() + ' time(s)'; } }}首先我們把服務(wù)協(xié)定的會(huì )話(huà)模式設置為允許會(huì )話(huà)(Allowed),在服務(wù)實(shí)現中,我為服務(wù)實(shí)現類(lèi)定義了一個(gè)計數器成員,每次調用都會(huì )將這個(gè)計數器加一,然后返回一句話(huà)告訴客戶(hù)端調用了多少次。
服務(wù)端的配置文件如下:
在這里我配置了支持會(huì )話(huà)的wsHttpBinding。
客戶(hù)端的調用代碼如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication2{ class Program { static void Main(string[] args) { ConsoleApplication2.ServiceReference1.HelloWCFClient client = new ServiceReference1.HelloWCFClient(); Console.WriteLine(client.HelloWCF()); Console.WriteLine(client.HelloWCF()); client.Close(); Console.Read(); } }}就是連續調用兩次服務(wù)端的方法并輸出結果。
F5運行一下,會(huì )看到下面的結果:
我們看到提示調用了兩次,也就是說(shuō)服務(wù)端記住了客戶(hù)端,當他第二次調用的時(shí)候將將計數器加一,就返回了調用兩次。當然這個(gè)局面的形成還受到實(shí)例上下文模式為PerSession的影響,我們后面會(huì )展開(kāi),總之服務(wù)協(xié)定支持會(huì )話(huà),才出現了這個(gè)局面。
如果我們把SessionMode改成NotAllowed,其他不改動(dòng),結果就會(huì )是下面的樣子:
結果兩次都是1,說(shuō)明服務(wù)器在第二次受到調用的時(shí)候已經(jīng)忘記了之前那個(gè)客戶(hù)端,他又分配了一個(gè)新的計數器給這個(gè)客戶(hù)端,所以計數就總是1了。
其實(shí)這個(gè)例子是很粗糙的,這里面還有些其他的影響因素,我們就是通過(guò)這個(gè)例子來(lái)看看SessionMode的一方面影響。
4. 總結
這一篇的內容比較少,我們應該記住一些要點(diǎn),在以后接觸更多特性的時(shí)候才不會(huì )混淆。
(1) 是否支持會(huì )話(huà)首先取決于選擇的綁定。
(2) 是否支持會(huì )話(huà)通過(guò)配置服務(wù)協(xié)定的ServiceContract屬性的SessionMode屬性實(shí)現的。
聯(lián)系客服