面向流的传输(如 TCP 和命名管道)在客户端和服务器之间的连续字节流上运行。 此流由对象 Stream 实现。 在流升级中,客户端希望向通道堆栈添加可选协议层,并要求信道的另一端执行此作。 流升级包括将原始 Stream 对象替换为已升级的对象。
例如,可以直接在传输流的基础上生成压缩流。 在这种情况下,原始传输 Stream 将替换为围绕原始传输流包装压缩 Stream 的传输流。
可以应用多次流升级,每次升级都包装前一次升级。
流升级如何工作
流升级过程有四个组件。
升序流发起者启动该过程:在运行时,它可以请求连接另一端,以升级通道传输层。
升级流 接受器 执行升级:在运行时,它会从另一台计算机接收升级请求,如果可能,则接受升级。
升级提供程序会在客户端创建发起程序,并在服务器上创建接受器。
流升级绑定元素将添加到服务和客户端上的绑定,并在运行时创建提供程序。
请注意,如果要进行多个升级,则发起程序和接受程序将会封装状态计算机,以便强制实施哪些升级转变对于每次“发起”都是有效的。
如何实现流升级
Windows Communication Foundation (WCF) 提供四个可以实现的 abstract
类:
若要实现自定义流升级,请执行以下步骤。 此过程在客户端和服务器计算机上执行简化的流升级流程。
创建用于实现 StreamUpgradeInitiator 的类。
重写要在所升级的流中采用的 InitiateUpgrade 方法,并返回升级后的流。 此方法同步工作;有类似的方法可以异步启动升级。
重写 GetNextUpgrade 方法以检查其他升级。
创建用于实现 StreamUpgradeAcceptor 的类。
重写要在所升级的流中采用的 AcceptUpgrade 方法,并返回升级后的流。 此方法同步工作;有类似的方法可以异步接受升级。
重写 CanUpgrade 方法,以确定在升级过程中的此时该升级接受程序是否支持请求的升级。
创建一个实现StreamUpgradeProvider的类。 重写 CreateUpgradeAcceptor 方法和 CreateUpgradeInitiator 方法,以返回步骤 2 和步骤 1 中定义的接受程序和发起程序的实例。
创建用于实现 StreamUpgradeBindingElement 的类。
在客户端上重写 BuildClientStreamUpgradeProvider 方法,然后在服务上重写 BuildServerStreamUpgradeProvider 方法。
在客户端上重写 BuildChannelFactory 方法,然后在服务上重写 BuildChannelListener 方法,以便将升级“绑定元素”添加到 BindingParameters。
将新的流升级绑定元素添加到服务器计算机和客户端计算机上的绑定。
安全升级
添加安全升级是常规流升级过程的专用版本。
WCF 已提供两个绑定元素来升级流安全性。 传输级别安全性的配置由WindowsStreamSecurityBindingElement和SslStreamSecurityBindingElement封装,这些元素可以配置并添加到自定义绑定中。 这些绑定元素扩展了用于构建客户端和服务器流升级提供程序的StreamUpgradeBindingElement 类。 这些绑定元素具有用于创建专用安全流升级提供程序类的方法,而这些类不是public
。因此,在这两种情况下,您只需将绑定元素添加到绑定中即可。
对于上述两个绑定元素未满足的安全场景,三个与安全相关的 abstract
类派生自上述发起者、接受者和提供程序基类:
实现安全流升级的过程与以前的升级过程基本相同,不同的是将从这三个类进行派生。 重写这些类中的其他属性以便为运行时提供安全信息。
多个升级
若要创建其他升级请求,请重复上述过程:创建其他扩展 StreamUpgradeProvider 和绑定元素。 将绑定元素添加到绑定。 从添加到绑定的第一个绑定元素开始,其余的绑定元素将被顺序处理。 在BuildChannelFactory和BuildChannelListener中,每个升级提供程序都可以确定如何在任何预先存在的升级绑定参数上对自身进行分层。 然后,它应将现有升级绑定参数替换为新的复合升级绑定参数。
或者,一个升级提供程序可以支持多个升级。 例如,你可能想要实现支持安全性和压缩的自定义流升级提供程序。 执行以下步骤:
用于编写创建发起方和接受器的提供程序类的子类 StreamSecurityUpgradeProvider 。
创建 StreamSecurityUpgradeInitiator 的子类,确保重写 GetNextUpgrade 方法以按顺序返回压缩流和安全流的内容类型。
子类 StreamSecurityUpgradeAcceptor ,用于了解其 CanUpgrade 方法中的自定义内容类型。
每次调用 GetNextUpgrade 和 CanUpgrade 之后,都会升级该流。