|
信道管理器是信道的創(chuàng)建者,一般來(lái)說(shuō)信道棧的中每個(gè)信道對(duì)應(yīng)著一個(gè)信道管理器。基于不同的消息處理的功能,將我們需要將相應(yīng)的信道按照一定的順序能組織起來(lái)構(gòu)成一個(gè)信道棧,由于信道本身是由信道管理器創(chuàng)建的,所以信道對(duì)應(yīng)的信道管理器也構(gòu)成一個(gè)信道管理器棧,棧中信道管理器的順序決定由它所創(chuàng)建信道的順序。
對(duì)于WCF的信道層來(lái)說(shuō),信道管理器在服務(wù)端和客戶端扮演著不同的角色,服務(wù)端的信道管理器在于監(jiān)聽(tīng)來(lái)自客戶端的請(qǐng)求,而客戶端的信道僅僅是單純的創(chuàng)建用于消息發(fā)送的信道。因此,客戶端的消息管理器又稱為信道監(jiān)聽(tīng)器(Channel Listener),客戶端的信道管理器則成為信道工廠(channel factory)。
在WCF中,所有的信道管理器,不管是位于服務(wù)端的信道監(jiān)聽(tīng)器還是客戶端的信道工廠,都繼承自一個(gè)基類:System.ServiceModel.Channels.ChannelManagerBase。ChannelManagerBase直接繼承自CommunicationObject,并實(shí)現(xiàn)了接口IDefaultCommunicationTimeouts。
public abstract class ChannelManagerBase : CommunicationObject, IDefaultCommunicationTimeouts { ...... }
1. 信道監(jiān)聽(tīng)器(Channel Listener)
其實(shí)我們完全可以把一個(gè)WCF應(yīng)用開成是一個(gè)普通的基于監(jiān)聽(tīng)-請(qǐng)求模式的網(wǎng)絡(luò)應(yīng)用,服務(wù)端將監(jiān)聽(tīng)器綁定到一個(gè)或一組URI上進(jìn)行網(wǎng)絡(luò)監(jiān)聽(tīng),一旦成功監(jiān)聽(tīng)到來(lái)自客戶端的請(qǐng)求,則接收、處理該請(qǐng)求,如需回復(fù)則發(fā)送回復(fù)回客戶端。在整個(gè)過(guò)程中,監(jiān)聽(tīng)器處于核心的地位,而WCF中的信道監(jiān)聽(tīng)器就起著這樣的作用。
1.1. 關(guān)于信道監(jiān)聽(tīng)器的監(jiān)聽(tīng)過(guò)程
熟悉網(wǎng)絡(luò)編程的朋友一定會(huì)對(duì)套節(jié)字應(yīng)用編程接口(Berkeley Sockets API)不會(huì)陌生,通過(guò)Socket API,我們很容易的創(chuàng)建基于網(wǎng)絡(luò)監(jiān)聽(tīng)-請(qǐng)求的應(yīng)用程序。在.NET編程環(huán)境下,我們將System.NET.Sockets.TcpListener 或者System.NET.Sockets.Socket 對(duì)象綁定到一個(gè)URI上,讓他們監(jiān)聽(tīng)來(lái)自客戶端的連接。當(dāng)連接請(qǐng)求被成功監(jiān)測(cè)到,調(diào)用Accept相關(guān)方法或者方法創(chuàng)建一Socket或者TcpClient對(duì)象,并通過(guò)這些對(duì)象獲得請(qǐng)求消息。
WCF中的信道監(jiān)聽(tīng)器與之相似。當(dāng)我們對(duì)一個(gè)服務(wù)進(jìn)行寄宿的時(shí)候,會(huì)為之添加一個(gè)或者多個(gè)終結(jié)點(diǎn)。對(duì)于一個(gè)終結(jié)點(diǎn)來(lái)說(shuō),它具有一個(gè)代表邏輯地址的終結(jié)點(diǎn)地址,還有一個(gè)代表物理地址的監(jiān)聽(tīng)地址(關(guān)于邏輯地址和物理地址,請(qǐng)參閱第二章),如果監(jiān)聽(tīng)地址(ListenUri)沒(méi)有顯式地指定,則監(jiān)聽(tīng)地址和邏輯地址共享相同的URI。對(duì)于每一個(gè)不同監(jiān)聽(tīng)地址,WCF會(huì)通過(guò)具體的綁定對(duì)象創(chuàng)建一個(gè)信道監(jiān)聽(tīng)器。信道監(jiān)聽(tīng)器通過(guò)調(diào)用AcceptChannel創(chuàng)建監(jiān)聽(tīng)信道棧,位于信道棧的第一個(gè)信道被成功返回。
一旦消息請(qǐng)求被成功監(jiān)聽(tīng),如果該信道是InputChannel(數(shù)據(jù)報(bào)MEP) 或者DuplexChannel(雙工MEP),則調(diào)用Receive或者BeginReceive方法接收消息,如果需要向?qū)ο蟀l(fā)送消息,則通過(guò)Send或者BeginSend將消息發(fā)給請(qǐng)求者;如果信道是ReplyChannel(請(qǐng)求/回復(fù)MEP)則調(diào)用ReceiveRequest方法獲得一個(gè)RequestContext對(duì)象,通過(guò)該對(duì)象獲取請(qǐng)求消息并發(fā)送回復(fù)消息。
1.2. 信道監(jiān)聽(tīng)器相關(guān)的接口和基類
由于信道監(jiān)聽(tīng)器是位于服務(wù)端的信道管理器,所以所有的信道監(jiān)聽(tīng)器均繼承自基類:ChannelManagerBase。同時(shí)由于信道監(jiān)聽(tīng)器具有其特殊的請(qǐng)求監(jiān)聽(tīng)的功能,所以WCF還定義一些相關(guān)的接口,比如System.ServiceModel.Channels.IChannelListener和System.ServiceModel.Channels.IChannelListener。
IChannelListener繼承自ICommnucationObject接口。定義了一組WaitForChannel和BeginWaitForChannel/EndWaitForChannel以同步和異步的方式判斷是否具有一個(gè)可用的信道;GetProperty和IChannel的GetProperty相對(duì);Uri屬性返回真正的監(jiān)聽(tīng)地址。
public interface IChannelListener : ICommunicationObject{ IAsyncResult BeginWaitForChannel(TimeSpan timeout, AsyncCallback callback, object state); bool EndWaitForChannel(IAsyncResult result); T GetProperty() where T : class; bool WaitForChannel(TimeSpan timeout); Uri Uri { get; }}
范型類型的IChannelListener繼承自IChannelListener,范型類型TChannel是一個(gè)實(shí)現(xiàn)了IChannel的類,一般來(lái)說(shuō),TChannel代表基于某種channel shape的Channel, 比如實(shí)現(xiàn)了IOutputChannel、IInputChannel、IRequestChanne、IReplyChannel、IDuplexChannel的IChannel類型。定義在IChannelListener的AcceptChannel和BeginAcceptChannel/EndAcceptChannel在連接請(qǐng)求被監(jiān)聽(tīng)到時(shí),以同步或者異步的方式創(chuàng)建信道棧用于消息的接收。
public interface IChannelListener : IChannelListener, ICommunicationObject where TChannel : class, IChannel{ // Methods TChannel AcceptChannel(); TChannel AcceptChannel(TimeSpan timeout); IAsyncResult BeginAcceptChannel(AsyncCallback callback, object state); IAsyncResult BeginAcceptChannel(TimeSpan timeout, AsyncCallback callback, object state); TChannel EndAcceptChannel(IAsyncResult result);}
除了定義兩個(gè)接口外,WCF中還定義了與這兩個(gè)接口向?qū)?yīng)的抽象基類:System.ServiceModel.Channels.ChannelListenerBase和System.ServiceModel.Channels.ChannelListenerBase。ChannelListenerBase實(shí)現(xiàn)了接口IChannelListener,而ChannelListenerBase實(shí)現(xiàn)了接口IChannelListener。
public abstract class ChannelListenerBase : ChannelManagerBase, IChannelListener, ICommunicationObject{ ... ...}public abstract class ChannelListenerBase : ChannelListenerBase, IChannelListener, IChannelListener, ICommunicationObject where TChannel : class, IChannel{ ... ...}
圖3-13所示的類圖大體上表示了上述的這些基類和接口之間的關(guān)系:
圖3-13 信道監(jiān)聽(tīng)器接口與基類
1.3. 案例演示3-3:如何自定義信道監(jiān)聽(tīng)器
在上面一節(jié)的案例演示中,我們創(chuàng)建了兩個(gè)用于請(qǐng)求-回復(fù)消息交換模式下的自定義信道,一個(gè)是實(shí)現(xiàn)了IRequestChannel的SimpleRequestChannel.,另一個(gè)是實(shí)現(xiàn)了IReplyChannel的SimpleReplyChannel。在本案例以及接下來(lái)的案例演示中,我們將為這兩個(gè)自定義創(chuàng)建兩個(gè)相應(yīng)的信道管理器,其實(shí)一個(gè)是用于創(chuàng)建SimpleRequestChannel的自定義信道工廠,另一個(gè)則是創(chuàng)建SimpleReplyChannel的自定義信道監(jiān)聽(tīng)器。先來(lái)看看我們自定義的信道監(jiān)聽(tīng)器SimpleChannelListener。該類繼承自范型的ChannelListenerBase:
public class SimpleChannelListener : ChannelListenerBase where TChannel : class, IChannel{ ... ...}
我們說(shuō)過(guò)信道一般不會(huì)孤立地存在,而是存在于一個(gè)由多個(gè)信道按照一定順序構(gòu)成的信道棧中。由于信道管理器是信道的締造者,要?jiǎng)?chuàng)建整個(gè)信道棧,同樣需要這些信道對(duì)應(yīng)的信道管理器按照相應(yīng)的順序組成一個(gè)信道管理器棧。反映在具體實(shí)現(xiàn)上,當(dāng)執(zhí)行了某個(gè)方法之后,需要調(diào)用棧中后一個(gè)信道監(jiān)聽(tīng)器相應(yīng)的方法,所以在SimpleChannelListener中,定義一個(gè)字段_innerChanneListener,代表?xiàng)V信c之相鄰的信道監(jiān)聽(tīng)器。_innerChanneListener通過(guò)在構(gòu)造函數(shù)中指定的BindingContext對(duì)象創(chuàng)建。關(guān)于BindingContext,我將在后面的一節(jié)中左詳細(xì)的介紹。
public class SimpleChannelListener : ChannelListenerBase where TChannel : class, IChannel{ ... ... private IChannelListener _innerChanneListener; public SimpleChannelListener(BindingContext context) { PrintHelper.Print(this, "SimpleChannelListener"); this._innerChanneListener = context.BuildInnerChannelListener(); }}
對(duì)于SimpleChannelListener來(lái)說(shuō),它的最重要的功能就是創(chuàng)建我們自定義的ReplyChannel:SimpleReplyChannel。SimpleReplyChannel的創(chuàng)建實(shí)現(xiàn)在OnAcceptChannel和OnEndAcceptChannel方法中。在構(gòu)造SimpleReplyChannel的innerChannel通過(guò)_innerChanneListener的AcceptChannel方法創(chuàng)建。
public class SimpleChannelListener : ChannelListenerBase where TChannel : class, IChannel{ ... ... protected override TChannel OnAcceptChannel(TimeSpan timeout) { PrintHelper.Print(this, "OnAcceptChannel"); IReplyChannel innerChannel = this._innerChanneListener.AcceptChannel(timeout) as IReplyChannel; return new SimpleReplyChannel(this, innerChannel) as TChannel; } protected override IAsyncResult OnBeginAcceptChannel(TimeSpan timeout, AsyncCallback callback, object state) { PrintHelper.Print(this, "OnBeginAcceptChannel"); return this._innerChanneListener.BeginAcceptChannel(timeout, callback, state); } protected override TChannel OnEndAcceptChannel(IAsyncResult result) { PrintHelper.Print(this, "OnEndAcceptChannel"); return new SimpleReplyChannel(this,this._innerChanneListener.EndAcceptChannel(result) as IReplyChannel) as TChannel; }}
對(duì)于定義在基類必須實(shí)現(xiàn)的抽象方法來(lái)說(shuō),為了簡(jiǎn)單起見(jiàn),我們僅僅是通過(guò)PrintHelper輸出當(dāng)前執(zhí)行的方法名稱,然后調(diào)用_innerChanneListener的相應(yīng)的方法就可以了:
public class SimpleChannelListener : ChannelListenerBase where TChannel : class, IChannel{ ... ... protected override IAsyncResult OnBeginWaitForChannel(TimeSpan timeout, AsyncCallback callback, object state) { PrintHelper.Print(this, "OnBeginWaitForChannel"); return this._innerChanneListener.BeginWaitForChannel(timeout, callback, state); } protected override bool OnEndWaitForChannel(IAsyncResult result) { PrintHelper.Print(this, "OnEndWaitForChannel"); return this._innerChanneListener.EndWaitForChannel(result); } protected override bool OnWaitForChannel(TimeSpan timeout) { PrintHelper.Print(this, "OnWaitForChannel"); return this._innerChanneListener.WaitForChannel(timeout); } ... ...}
WCF中的綁定模型:
[WCF中的Binding模型]之一: Binding模型簡(jiǎn)介
[WCF中的Binding模型]之二: 信道與信道棧(Channel and Channel Stack)
[WCF中的Binding模型]之三:信道監(jiān)聽(tīng)器(Channel Listener)
[WCF中的Binding模型]之四:信道工廠(Channel Factory)
[WCF中的Binding模型]之五:綁定元素(Binding Element)
[WCF中的Binding模型]之六:從綁定元素認(rèn)識(shí)系統(tǒng)預(yù)定義綁定
NET技術(shù):[WCF的Binding模型]之三:信道監(jiān)聽(tīng)器(Channel Listener),轉(zhuǎn)載需保留來(lái)源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。