Share via


Channels Illustrated

In the channel development series last week, we looked at the characteristics of channels (protocol channels, transport channels, and why you would write a channel at all). Let's use a specific example to illustrate those points. Although the protocol for reliable messaging is quite complex, the basic intent of the channel can be described quite simply. We'll keep the discussion simpler by only talking about the send side of the server response. You can map this yourself to the client side or to receiving messages, but this example doesn't need a lot of details to get the point across.

Here's a channel stack that contains the reliable messaging channel.

When the server sends a message out to the client, that message passes through the upper protocol channels in the channel stack. Those protocol channels can create, alter, or destroy messages along the way, but let's say that the message arrives intact to the reliable messaging channel. The reliable messaging channel first makes a copy of the message just in case delivery fails in the future. The reliable messaging channel then sends the message down through the remaining protocol channels. Again, we'll assume that nothing happens along the way; the message gets to the transport and is sent over the network. Sometimes, despite the best efforts of this process, the client never receives the message. In that case, the reliable messaging channel will produce another copy of the message from its store and send it again. Eventually, the client will either acknowledge receipt of the message or the two sides will decide to give up due to their inability to communicate. When the message is acknowledged, the reliable messaging channel throws its copy away as the message is no longer needed.

Let's check against the criteria for writing channels to see if a channel was really needed to perform reliable messaging.

1.
Did we need a new component that interfaces with the network? No, there was some other component in the channel stack that handled the network for us.

2.
Did we need to establish a pattern of message exchange? Yes, the pattern of retries and acknowledgement is something that's different from the exchange inherent in a service call.

3.
Did we need to have a protocol for expressing the messages? Yes, although we didn’t talk about the details of that protocol in this example. We need some way of describing what data is, what acknowledgments are, and when retries are occurring.

4.
Did we need something other than a one-to-one correspondence between input and output? Yes, there could have been any number of output messages due to retries.

5.
Did we need to perform an operation that cannot be represented as a method call? Yes, there's no way to make a method call that would compose with the other protocol channels.

It looks like channels are the only extensibility point that can perform reliable messaging.

Next time: A Trick with Faults