通道形状介绍
通道形状是我们对通道进行分类的重要依据之一。概念上,一个通道形状对 应于一个或多个消息交换模式(MEPs),第3章“消息交换模式、拓扑与编排”里 曾经讨论过这个概念。为了说明问题,考虑一下发送者和接收者使用请求/应答 模式来交换消息的情况。在请求/应答模式里,发送者发送消息给接收者,接收 者回复消息给发送者,请求消息和应答消息之间的关系是固定的。因为通道是发 送者和接收者交换消息的物理途径,发送者和接收者必须建立它们自己的通道。 当发送者和接收者通过请求 /应答模式来交换消息的时候,发送者和接收者必须 理解请求/应答模式的规则。在结构上来说,这意味着发送者上的通道要定义发 送消息和接收消息的成员。此外,发送者和接收者需要定义关联请求消息和应答 消息的成员。
咋一看,发送者和接收者有着相同的角色。例如,发送者和接收者都可以发 送和接收消息。逻辑上的区别就是发送和接收消息过程中的顺序不同。这意味着 发送者和接收者上的通道会略有不同。这些不同点体现在发送者和接收者通道里 定义的成员上。通道形状是我们命名和划分这些不同点的方式。因为.NET接口是 鉴别.NET类型成员的天然方式,所以它们也是区别通道形状的最佳方式。
WCF类型系统定义了几个描述不同通道形状的接口,这些接口与第三章里讲述 的消息交换模式一一对应。图6-2列举了消息交换模式(MEP)、发送者和接受之 间的对应关系。这些接口都定义在System.ServiceModel.Channels命名空间下。
图6-2消息交换模式(MEP)与通道形状的关系 | ||
MEP | Sender | Receiver |
数据报 | IOutputChannel | IInputChannel |
请求/应答 | IRequestChannel | IReplyChannel |
双工 | IDuplexChannel | IDuplexChannel |
P2P | IDuplexChannel | IDuplexChannel |
注意,这里报文和请求/应答模式的接口是不同的。对于报文MEP,发送者发 送一个消息,但是不能接收消息,而请求/应答模式是可以的。记住, IOutputChannel 定义了一个名为Send的方法,而IInputChannel定义了一个名为 Receive的方法。
这里还需要解释一下表6-2里的双工MEP。记住双工MEP里,发送者和接收者都 可以发送和接受消息。在成员级别上,两者都可以定义一个名为一个名为Send和 一个名为Receive的方法。
实际上,消息程序需要把多个消息关联到一起。例如,一个交易系统(发送 者)也许要发送关于一个交易订单或者产品的多个消息到财务系统(接收者)。 这个关联的逻辑边界就是会话(session)。当第一次考虑这些会话的时候,很 容易理解为接收者会根据发送者来关联这些消息。这样一来,很自然地就会猜想 ,同时处理5个发送者请求的接收者将会把消息关联到一个特定的发送者上,正 像ASP.NET程序处理来自于多个浏览器的请求消息一样。在WCF应用程序里,这些 耦合过于紧密以至于不能满足过多的消息需求。例如,一个交易系统(发送者) 或许发送多个订单有关的消息,财务系统(接收者)也许要根据需订单实例而不 是交易系统(发送者)来关联这些消息。
WCF会话是一个通道级别的构造。因为这个概念也就是为了关联消息,每个通 道都自己关联消息的方式。例如,TCP/IP 通道能够根据接收消息的socket来关 联同一个会话里的消息。与之相对的是,实现了WS-ReliableMessaging规范的通 道,可以在消息头里使用ID属性来关联同一个会话里的消息,所以,这也就不需 要依赖具体的socket或者传输结构了,就可以实现同一个会话里消息的关联。
所有支持会话的通道的一个共同特性就是它们可以拥有自己的标识符,WCF基 础结构里的不同模块都可以使用这个标识符来关联消息。概念上看,通道需要实 现System.ServiceModel.Channels.ISessionChannel<T>接口来会支持会 话。ISessionChannel<T>的泛型参数必须实现 System.ServiceModel.Channels.ISession接口。下面代码展示了这些接口里的 成员:
public interface ISession {
String Id { get; }
}
public interface ISessionChannel<T> where T: ISession {
T Session { get; }
}