[Remoting] 五:信道
信道(Channel)是 Remoting 体系的承载平台,负责处理客户端和服务器之间的通讯,其内容包括跨域通讯、消息传递、对象编码等等。信道必须实现 IChannel 接口,根据通讯方向又分别提供了继承版本 IChannelReceiver 和 IChannelSender。Remoting 框架为我们提供了 IPC、TCP 以及 HTTP 的实现版本,当然我们还可以在网络上找到其他协议的实现版本。
我们可以使用实用类 ChannelServices 来管理程序域内的信道,诸如注册、注销等等。程序域内可以同时使用多个信道,每个信道需提供唯一的名称,以便 ChannelServices 进行管理,同时信道会随程序域的退出自动销毁。
信道内部包含由多个接收器(Sink)组成的接收链(Sink Chain)。接收器用于处理客户端和服务器之间的来往消息,诸如格式化程序接收器(FormatterSink)、传输接收器(TransportSink)或堆栈生成器接收器(StackBuilderSink)等等。每个接收器或实现 IClientChannelSink,或实现 IServerChannelSink。
Remoting 采用信道接收提供程序(Channel Sink Provider,实现 IClientChannelSinkProvider、IClientFormatterSinkProvider 或 IServerChannelSinkProvider 接口的对象) 来创建接收器,已有的提供程序包括 BinaryClientFormatterSinkProvider / BinaryServerFormatterSinkProvider、SoapClientFormatterSinkProvider / SoapServerFormatterSinkProvider。
在客户端接收链中第一个接收器通常是格式化程序接收器(IClientFormatterSink),且必须实现 IMessageSink。代理通过信道接收提供程序找个该接收器,并通过接口方法将消息传递给链中所有的接收器,最后由传输接收器发送到服务器。同样,在服务器排在最后的接收器是格式化程序接收器和堆栈生成器接收器,分别执行反序列化和将将消息转换成相应的调用堆栈。
只要看看 BinaryClientFormatterSinkProvider 和 BinaryClientFormatterSink 的代码就很容易理解如何使用提供者模型构造一个接收链了。
BinaryClientFormatterSinkProvider
BinaryClientFormatterSink
信道内的接收器是可 "插入的",这意味着我们可以实现自己的接收器,并将其装配到信道接收链中。比如对消息进行加密,或者对数据流进行压缩等等。
有关细节可参考:
《.NET Remoting Customization Made Easy: Custom Sinks》
《如何定制Sink扩展.Net Remoting功能》
TcpServerChannel channel = new TcpServerChannel(801);
ChannelServices.RegisterChannel(channel, false);
ChannelServices.RegisterChannel(channel, false);
我们可以使用实用类 ChannelServices 来管理程序域内的信道,诸如注册、注销等等。程序域内可以同时使用多个信道,每个信道需提供唯一的名称,以便 ChannelServices 进行管理,同时信道会随程序域的退出自动销毁。
TcpServerChannel channel = new TcpServerChannel("tcp801", 801);
ChannelServices.RegisterChannel(channel, false);
IChannel c2 = ChannelServices.GetChannel("tcp801");
Console.WriteLine(Object.ReferenceEquals(channel, c2));
channel.StopListening(null);
channel.StartListening(null);
foreach (IChannel c in ChannelServices.RegisteredChannels)
{
Console.WriteLine(c.ChannelName);
}
ChannelServices.UnregisterChannel(channel);
ChannelServices.RegisterChannel(channel, false);
IChannel c2 = ChannelServices.GetChannel("tcp801");
Console.WriteLine(Object.ReferenceEquals(channel, c2));
channel.StopListening(null);
channel.StartListening(null);
foreach (IChannel c in ChannelServices.RegisteredChannels)
{
Console.WriteLine(c.ChannelName);
}
ChannelServices.UnregisterChannel(channel);
信道内部包含由多个接收器(Sink)组成的接收链(Sink Chain)。接收器用于处理客户端和服务器之间的来往消息,诸如格式化程序接收器(FormatterSink)、传输接收器(TransportSink)或堆栈生成器接收器(StackBuilderSink)等等。每个接收器或实现 IClientChannelSink,或实现 IServerChannelSink。
Remoting 采用信道接收提供程序(Channel Sink Provider,实现 IClientChannelSinkProvider、IClientFormatterSinkProvider 或 IServerChannelSinkProvider 接口的对象) 来创建接收器,已有的提供程序包括 BinaryClientFormatterSinkProvider / BinaryServerFormatterSinkProvider、SoapClientFormatterSinkProvider / SoapServerFormatterSinkProvider。
在客户端接收链中第一个接收器通常是格式化程序接收器(IClientFormatterSink),且必须实现 IMessageSink。代理通过信道接收提供程序找个该接收器,并通过接口方法将消息传递给链中所有的接收器,最后由传输接收器发送到服务器。同样,在服务器排在最后的接收器是格式化程序接收器和堆栈生成器接收器,分别执行反序列化和将将消息转换成相应的调用堆栈。
TcpServerChannel channel = new TcpServerChannel("tcp801", 801, new BinaryServerFormatterSinkProvider());
ChannelServices.RegisterChannel(channel, false);
...
TcpClientChannel channel = new TcpClientChannel("tcp801", new BinaryClientFormatterSinkProvider());
ChannelServices.RegisterChannel(channel, false);
ChannelServices.RegisterChannel(channel, false);
...
TcpClientChannel channel = new TcpClientChannel("tcp801", new BinaryClientFormatterSinkProvider());
ChannelServices.RegisterChannel(channel, false);
只要看看 BinaryClientFormatterSinkProvider 和 BinaryClientFormatterSink 的代码就很容易理解如何使用提供者模型构造一个接收链了。
BinaryClientFormatterSinkProvider
public IClientChannelSink CreateSink(IChannelSender channel, string url, object remoteChannelData)
{
IClientChannelSink sink1 = null;
if (this._next != null)
{
sink1 = this._next.CreateSink(channel, url, remoteChannelData);
if (sink1 == null)
{
return null;
}
}
SinkChannelProtocol protocol1 = CoreChannel.DetermineChannelProtocol(channel);
BinaryClientFormatterSink sink2 = new BinaryClientFormatterSink(sink1);
sink2.IncludeVersioning = this._includeVersioning;
sink2.StrictBinding = this._strictBinding;
sink2.ChannelProtocol = protocol1;
return sink2;
}
{
IClientChannelSink sink1 = null;
if (this._next != null)
{
sink1 = this._next.CreateSink(channel, url, remoteChannelData);
if (sink1 == null)
{
return null;
}
}
SinkChannelProtocol protocol1 = CoreChannel.DetermineChannelProtocol(channel);
BinaryClientFormatterSink sink2 = new BinaryClientFormatterSink(sink1);
sink2.IncludeVersioning = this._includeVersioning;
sink2.StrictBinding = this._strictBinding;
sink2.ChannelProtocol = protocol1;
return sink2;
}
BinaryClientFormatterSink
public BinaryClientFormatterSink(IClientChannelSink nextSink)
{
this._includeVersioning = true;
this._channelProtocol = SinkChannelProtocol.Other;
this._nextSink = nextSink;
}
public IClientChannelSink NextChannelSink
{
get
{
return this._nextSink;
}
}
{
this._includeVersioning = true;
this._channelProtocol = SinkChannelProtocol.Other;
this._nextSink = nextSink;
}
public IClientChannelSink NextChannelSink
{
get
{
return this._nextSink;
}
}
信道内的接收器是可 "插入的",这意味着我们可以实现自己的接收器,并将其装配到信道接收链中。比如对消息进行加密,或者对数据流进行压缩等等。
有关细节可参考:
《.NET Remoting Customization Made Easy: Custom Sinks》
《如何定制Sink扩展.Net Remoting功能》