[老老實實學WCF] 第七篇 會話

老老實實學WCF

第七篇 會話

 

通過前幾篇的學習,我們已經掌握了WCF的最基本的編程模型,我們已經可以寫出完整的通信了。從這篇開始我們要深入地瞭解這個模型的高級特性,這些特性用來保證我們的程序運行的高效、穩定和安全。

 

首先我們來學習會話。

 

1. 什麼是會話

會話是通信雙方進行通信的一個時間片、一個語境或者說一個上下文,在這個特定的環境中,通信的雙方是彼此認識的,就像兩個人在聊天,他們都很清楚誰在聆聽自己講話,也很清楚對方講的話是給自己聽的,簡單的說就是通信雙方是可以記住彼此的。

 

一旦會話結束了,通信雙方就忘記了彼此,即使他們再次建立會話,他們也不會記得他們上次會話的內容,也就是他們不記得他們曾經見過面。

 

這在我們現實世界中或許很難想象,但是在通信的世界裏就是這樣的。服務端不可能記住每個跟他通信的人,他只能在一段時間內(會話)記住一個人。

 

這個特性是很有用的,有些邏輯需要客戶端和服務端通信多次才能完成,在這個期間雙方需要記住彼此,而且會話也是很多其他特性實現的基礎,例如雙工通信。

2. 如何建立會話

那麼我們要想建立一個會話通信,應該具備怎樣的條件呢?

(1) 需要支持會話的綁定。綁定描述了雙方的通信方式,不同的綁定對會話的支持是不同的,比如basicHttpBinding是不支持會話的,而wsHttpBinding就是支持的。要建立會話通信,這個通信必須首先使用支持會話的綁定。

(2) 讓服務協定支持會話,服務協定實際上就是通信的通道(見第四、五篇),讓服務協定支持會話,那麼就可以在這個通信通道上支持會話了。

 

選擇支持會話的綁定我們知道怎麼做,可如何讓服務協定支持會話呢?要用到在修飾服務協定的SeviceContract屬性,我們知道被這個屬性修飾的接口是一個服務協定,其實這個屬性也擁有屬性,其中一個屬性叫做SessionMode。這是一個枚舉,我們通過設置這個枚舉的值來配置服務協定是否支持會話。例如:

[ServiceContract(SessionMode = SessionMode.Required)]
    public interface IHelloWCF
    {
        [OperationContract]
        string HelloWCF();
    }

這段代碼中,我把SessionMode設置爲了Required,這表示調用這個服務協定的客戶端必須使用會話。

SessionMode有三個可能的值:

1) Allowed:這是默認值,表示這個服務協定是允許會話的,客戶端可以選擇用會話連接,也可以選擇不用會話連接。

2) Required:表示服務協定要求客戶端連接必須使用會話。

3) NotAllowed:表示服務協定不允許使用會話連接。

 

這些配置需要搭配其他的配置才能起到實際意義,比如服務實例模式,服務端和客戶端調用模式等等,等我們瞭解到這些特性的時候再展開,現在我們只需要知道,前兩種配置是支持會話的,第三種是不支持的。

3. 一個簡單的例子

我們通過一個簡單的例子來看看允許會話與不允許的區別,我修改了前幾篇中寄存在IIS中的服務,代碼如下:

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)";
        }
    }
}

首先我們把服務協定的會話模式設置爲允許會話(Allowed),在服務實現中,我爲服務實現類定義了一個計數器成員,每次調用都會將這個計數器加一,然後返回一句話告訴客戶端調用了多少次。

服務端的配置文件如下:

<configuration>
  <system.serviceModel>
    <services>
      <service name="LearnWCF.HelloWCFService" behaviorConfiguration="metadataExchange">
        <endpoint address="" binding="wsHttpBinding" contract="LearnWCF.IHelloWCF"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataExchange">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

在這裏我配置了支持會話的wsHttpBinding。

 

客戶端的調用代碼如下:

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();
        }
    }
}

就是連續調用兩次服務端的方法並輸出結果。

F5運行一下,會看到下面的結果:

我們看到提示調用了兩次,也就是說服務端記住了客戶端,當他第二次調用的時候將將計數器加一,就返回了調用兩次。當然這個局面的形成還受到實例上下文模式爲PerSession的影響,我們後面會展開,總之服務協定支持會話,纔出現了這個局面。

 

如果我們把SessionMode改成NotAllowed,其他不改動,結果就會是下面的樣子:

結果兩次都是1,說明服務器在第二次受到調用的時候已經忘記了之前那個客戶端,他又分配了一個新的計數器給這個客戶端,所以計數就總是1了。

 

其實這個例子是很粗糙的,這裏面還有些其他的影響因素,我們就是通過這個例子來看看SessionMode的一方面影響。

 

4. 總結

這一篇的內容比較少,我們應該記住一些要點,在以後接觸更多特性的時候纔不會混淆。

(1) 是否支持會話首先取決於選擇的綁定。

(2) 是否支持會話通過配置服務協定的ServiceContract屬性的SessionMode屬性實現的。

 




 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章