Channel shape is one of the key means by which we categorize channels. Conceptually, a channel shape corresponds to one or more Message Exchange Patterns (MEPs), as discussed in Chapter 3, “Message Exchange Patterns, Topologies, and Choreographies.” To illustrate, consider a sender and a receiver that are exchanging messages as prescribed by the Request/Reply MEP. In Request/Reply, the sender sends a message to the receiver, and the receiver sends a reply message back to the sender, and the correlation between the request and the reply is implicit. Because channels are the physical means by which senders and receivers send and receive messages, both the sender and receiver must build their own channels. When the sender and receiver are exchanging messages via the Request/Reply MEP, the sending and receiving channels must understand the rules of the Request/Reply MEP. Structurally, this means that the channels on the sender define members specific to sending a request message and receiving a reply message. On the other end of the message exchange, the channels on the receiver must define members specific to receiving a request message and sending a reply message. In addition, both the sender and the receiver define members that correlate the request and the reply.
At first glance, it might seem that the sender and the receiver have identical roles. For example, it is true that both the sender and the receiver send and receive messages. The logical difference between the sender and the receiver is the order in which they send and receive messages. This difference in order means that the channels on the sender and the receiver must be slightly different. This difference manifests itself structurally as different members in sending and receiving channels. Channel shapes are the way we name and group these structural differences. Because .NET interfaces are a natural way to enforce the existence of members in a .NET type, they are a great way to identify the shape of a channel.
The WCF type system defines several interfaces that describe the different channel shapes, and these interfaces map to the MEPs described in Chapter 3. Table 6-2 lists the MEP-tointerface mapping for the sender and receiver. All interfaces listed in Table 6-2 are a part of the System.ServiceModel.Channels namespace.
MEP | Sender | Receiver |
---|---|---|
Datagram | IOutputChannel | IInputChannel |
Request/Reply | IRequestChannel | IReplyChannel |
Duplex | IDuplexChannel | IDuplexChannel |
P2P | IDuplexChannel | IDuplexChannel |
Notice that the interfaces for Datagram and Request/Reply are different on the sender and the receiver. With the Datagram MEP, the sender sends a message and is not able to receive a message, while the receiver is able to receive a message only. With this in mind, the IOutputChannel defines a method named Send and the IInputChannel defines a method named Receive.
The Duplex MEP entry in Table 6-2 warrants some explanation. Remember that the Duplex MEP blurs the distinction between the sender and the receiver since both the sender and receiver are free to send and receive messages at will. At the member level, both the sender and the receiver can define a method named Send and a method named Receive. Since the members can be identical on both the sender and the receiver, it is natural that sending and receiving channels implement the same interface in the Duplex MEP.
In practice, messaging applications need to correlate multiple messages. For example, a purchasing application (sender) might need to send multiple messages to an accounting application (receiver) in such a way that all messages are related to one purchase order or product. The logical boundary for this correlation is called a session. When initially considering sessions, the tendency might be to assume that the receiver correlates messages based on the sender. With this mindset, it is natural to assume that a receiver servicing five senders will relate a message to a particular sender, as in the case of an ASP.NET application servicing multiple browsers. In a WCF application, however, this coupling is too narrow to work for many known messaging requirements. For example, one purchasing application (sender) might send messages that are related to several purchase orders, and the accounting application (receiver) might need to correlate these messages based on the purchase order rather than the instance of the purchasing application (sender).
WCF sessions are an optional channel-level construct. Because the concept of a session is nothing more than a means to correlate messages, each channel can have its own way of correlating messages. For example, a TCP/IP transport channel can correlate messages in a session based on the socket it uses to receive messages. In contrast, the channel that implements WS-ReliableMessaging can use the ID message header to correlate messages in a session, thereby removing the dependence on a particular socket or transport construct.
The one characteristic common to all session-capable channels is that they have an identifier, and different parts of the WCF infrastructure can use this identifier to correlate messages. Structurally, a channel supports sessions when it implements the System.ServiceModel. Channels.ISessionChannel<T> interface. The generic parameter in ISessionChannel<T> must implement the System.ServiceModel.Channels.ISession interface. The following code snippet shows the members in these interfaces:
public interface ISession { String Id { get; } } public interface ISessionChannel<T> where T: ISession { T Session { get; } }
As the preceding code snippet shows, these interfaces expose a member named Id, and this member represents a session identifier. In WCF, channel types that implement the ISessionChannel<T> interface are said to be sessionful channels. For the sake of consistency, the WCF type system considers a sessionful channel as a variant on channel shape. In other words, the IDuplexChannel interface has a variant named IDuplexSessionChannel. From a shape perspective, the IDuplexSessionChannel has a different shape than the IDuplexChannel, even though they are both capable of duplex communication. The real difference between these interfaces is that the IDuplexSessionChannel implements the ISessionChannel<T> interface. Table 6-3 illustrates the sessionful channel shapes in the WCF type system.
MEP | Sender | Receiver |
---|---|---|
Datagram | IOutputSessionChannel | IInputSessionChannel |
Request/Reply | IRequestSessionChannel | IReplySessionChannel |
Duplex | IDuplexSessionChannel | IDuplexSessionChannel |
P2P | IDuplexSessionChannel | IDuplexSessionChannel |
Note | In contrast with the section “The Channel State Machine” earlier in this chapter, only channels implement the channel shape interfaces. Since channel factories create channels, they require a reference to the channel shape interface that describes the shape of the channels they create. |