In this post I will list down my understanding of the WCF Channel Model and how it is related to the ServiceHost class.This is the class we frequently use to host our services in a console program/windows service.First quickly let us take a look into the base class of the ServiceHost.It is an abstract class called ServiceHostBase which in turn derives from the CommunicationObject.CommunicationObject implements the ICommunicationObject interface which is the contract for providing all the state machine functionality in WCF.State machine receives various signals/events and moves from one state to another.For example a TCP socket can be a very good case of a state machine.
The possible states are defined by the CommunicationState enumeration are
- Created – Indicates the object is instantiated but not yet opened.
- Opening – Object is moving from Created to Opened
- Opened – Object is successfully opened
- Closing – Object is about to close
- Closed – Object is closed
- Faulted – Object has encountered an error and is not usable any more.
The state transition is done by the methods Open,Close & Abort and following events are raised
We can add some event handlers and check this out easily using a code as shown below:
host = new ServiceHost(typeof(SampleHost.TestService));
host.Opening += new EventHandler(host_Opening);
host.Opened += new EventHandler(host_Opened);
host.Closed += new EventHandler(host_Closed);
host.Closing += new EventHandler(host_Closing);
host.Faulted += new EventHandler(host_Faulted);
Now with fair understanding of CommunicationObject let us take look into what is happening in the Channel Layer.WCF channels are layers stacked over one another.Each channel provides some kind of abstraction to the channels above.The lowest layer is the Transport Channel which receives that raw bytes from the network sockets and convert them into an instance of the Message object.This Message object is passed to the channels above which are known as the Protocol Channels.These channels perform various tasks related encoding,formatting etc. and alters the Message.
At present we will concentrate only the channels in the server side i.e. the service channels.The two important interface in this respect are the IChannel and IChannelListener.Channel Listeners listen to the network or the underlying channels for messages and creates a channel upon receiving a message.The custom channel listeners needs to inherit from ChannelListenerBase class which implements the IChannelListener interface.ChannelListenerBase inherits CommunicationObject and implements the functionality of a state machine like the ServiceHost.ChannelListenerBase<TChannel> provides the AcceptChannel method which waits for and accepts an incoming channel.
Now we have understood that there is a series of channels processing the incoming messages.But how they are ultimately send to the appropriate operation in the service type?How they are related to the ServiceHost hosting the service?
Now we have to take a look at the dispatchers in the service model.
- ChannelDispatchers – ChannelDispatchers (ChannelDispatcher) accept incoming messages.Each ChannelDispatcher is associated with exactly one ChannelListener.ChannelListener receives the message as mentioned and the message is processed by channels.After the message is processed by the associated channels then ChannelDispatcher passes it on to a suitable EndpointDispatcher
- EndPointDispatchers – EndPointDispatchers are responsible for taking a message out of the channel stack and passing them to the right service operation.One of the key element of the EndpointDispatcher is the DispatchRuntime.DispatchRuntime provides facility to alter default service behaviour using custom classes to provide enhanced functionality related to Service Instancing,Error Handling,Security etc. The extended behaviour using DispatchRuntime are all applicable at the service level i.e. for all the operations of the service.DispatchRuntime contains the DispatchOperation which is responsible for routing the message to the right operation and providing customizations facilities applicable at the operation level.
Now the last piece of the puzzle is how they are related to the ServiceHost.
When we call ServiceHost.Open the following things happen:
- ChannelDispatchers are created and opened.There will be one ChannelDispatcher per URI using which service can be accessed including the endpoints exposing the metadata.
- Listeners associated with each ChannelDispatcher is created and opened.They wait to accept the incoming channels.
Similarly when ServiceHost.Close is called first the Listeners are closed and then the associated Dispatchers.