一種WCF檢測客戶端斷線方法
一般檢測客戶端斷線重連的方法都是使用心跳檢測。然而增加心跳檢測將會稍微影響系統的效能,總之這點資源開銷的瑕疵對於有強迫症的我來說有點難接受。在WCF裡面其實可以實現客戶端斷線檢測,而不需要心跳。
首先我要宣告,這個方法值適用於WCF服務的會話模式。相信一些資深WCF玩家已經猜到我要說的了。下面我來講解下
1、在基於會話模式的WCF服務中,每一個客戶端的連線通道都會有一個ID標示,通過它WCF服務可以甄別不同客戶端,從而為每個不同客戶端建立一個會話通道。
//這裡我們先對契約藉口屬性進行設定。
[ServiceContract (CallbackContract = typeof(ICalculatorCallback),SessionMode =SessionMode.Required)]
2、每一個客戶端連線的時候。WCF服務都會建立一個InstanceContext例項上下文,它與客戶端同生存週期。每一次建立例項上下文的時候,服務類(就是契約藉口的實現類)就會被重新建立(準備的說是重新呼叫其建構函式)例項消亡時候會自動進行垃圾回收。如下程式碼:
[ServiceBehavior(InstanceContextMode =InstanceContextMode.PerSession)] //在類上方新增服務行為,設定為會話模式。
public class Service1 : IService1,IDisposable //繼承IDisposable 藉口使得在垃圾回收的時候能夠呼叫Dispose函式
{
MessageProperties ms;
RemoteEndpointMessageProperty remp; //這兩個變數 用來回去客戶端的 地址和埠號。
public Service1()
{
//獲取遠端埠的IP和埠號。 可以利用來進行心跳檢測
Console.WriteLine(Thread.CurrentThread.ManagedThreadId+"構造器被呼叫");
ms = OperationContext.Current.IncomingMessageProperties;
remp = ms[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
Console.WriteLine("Get message from " + remp.Address + ":" + remp.Port+"已經連線伺服器");
}
public void plus(int a, int b)
{
//雙工通訊,呼叫客戶端實現的回撥函式。
ICalculatorCallback callback = OperationContext.Current.GetCallbackChannel<ICalculatorCallback>();
callback.showResult(a+b,a,b);
}
//如果客戶端斷開連線,會話就會關閉,例項上下文物件會被釋放,從而呼叫這個函式。這時我們就知道客戶端已經斷開連線了。
public void Dispose()
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId +"Dispose方法被呼叫");
Console.WriteLine("Get message from " + remp.Address + ":" + remp.Port + "已經離開伺服器");
}
~Service1()
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "終止化器被呼叫");
}
}
3. 所為這個檢測客戶端斷線的方式就是看會話通道是否關閉,如果客戶端斷開連線就會關閉會話垃圾回收機制就會釋放例項上下文。只要Dispose函式被呼叫就說明客戶端斷開連線。所以有關客戶端斷線的操作在這個函式裡面呼叫或者設定標識就可以了。
4.一些執行結果如下所示。
當我禁用本地網路介面卡,或者關閉客戶端時服務端都能檢測到客戶端斷線並呼叫Dispose函式 如下