Client-Side Messaging

As you know by now, the message is created by the combination of the TransparentProxy and RemotingProxy, which send it to the first entry of the message sink chain. After this creation, the message will pass four to six stages, depending on the channel's configuration. You can see this in Figure 7-6.

click to expand
Figure 7-6: Client-side layers and message stages

The contents of the preprocessing, formatting, and transfer layers are customizable during the creation of the channel. When creating a default HTTP channel, for example, only a SoapClientFormatterSink (as the formatting layer) and an HttpClientTransportSink (as the transport layer) will be created; by default neither a preprocessing layer nor any dynamic context sinks are registered.


I show the processing of synchronous messages in this examples. Asynchronous messages will be handled later in this chapter.

ClientContextTerminatorSink and Dynamic Sinks

The ClientContextTerminatorSink is automatically registered for all channels. It is the first sink that gets called and in turn notifies any dynamic context sinks associated with the current remoting context. These dynamic sinks will receive the message via the IDynamicMessageSink interface:

 public interface IDynamicMessageSink {     void ProcessMessageStart(IMessage reqMsg, bool bCliSide, bool bAsync);     void ProcessMessageFinish(IMessage replyMsg, bool bCliSide, bool bAsync); } 

These sinks don't need to pass the information to any other sink in a chain. Instead, this is done automatically by the context terminator sink, which will call the relevant methods on a list of registered dynamic sinks before passing the message on to the next IMessageSink.

You'll find more on the creation and implementation of dynamic sinks in Chapter 8.


After passing through optional custom IMessageSink objects, the message reaches the formatter. As shown previously, the formatter's task is to take the message's internal dictionary and serialize it to a defined wire format. The output of the serialization is an object implementing ITransferHeaders and a stream from which the channel sink will be able to read the serialized data.

After generating these objects, the formatter calls ProcessMessage() on its assigned IClientChannelSink and as a result starts to pass the message to the secondary chain—the channel sink chain.


At the end of the chain of client channel sinks, the message ultimately reaches the transfer channel, which also implements the IClientChannelSink interface. When the ProcessMessage() method of this channel sink is called, it opens a connection to the server (or uses an existing connection) and passes the data using the defined transfer protocol. The server now processes the request message and returns a ReturnMessage in serialized form. The client-side channel sink will take this data and split it into an ITransferHeader object, which contains the headers, and into a stream containing the serialized payload. These two objects are then returned as out parameters of the ProcessMessage() method.

After this splitting, the response message travels back through the chain of IClientChannelSinks until reaching the formatter, where it is deserialized and an IMessage object created. This object is then returned back through the chain of IMessageSinks until it reaches the two proxies. The TransparentProxy decodes the message, generates the method return value, and fills the respective out or ref parameters.

The original method call—which has been placed by the client application— then returns and the client now has access to the method's responses.

Advanced  .NET Remoting C# Edition
Advanced .NET Remoting (C# Edition)
ISBN: 1590590252
EAN: 2147483647
Year: 2002
Pages: 91
Authors: Ingo Rammer © 2008-2017.
If you may any questions please contact us: