65.9K
CodeProject 正在变化。 阅读更多。
Home

动态插入客户端通道接收器提供程序

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.42/5 (9投票s)

2003年4月11日

CPOL

2分钟阅读

viewsIcon

56625

downloadIcon

592

连接远程对象的所需通道的解决方法。

引言

.NET 远程处理架构以其灵活性和多功能性而闻名,
很少有局限性。

这里有一个我想指出的局限性。然后我将展示一个解决方法,利用
远程处理架构的出色灵活性,通过动态插入客户端通道接收提供程序。

问题:我有两个远程服务,名为 Knossos 和 Zakros,它们具有通道配置条目

对于 Knossos:

  <channel ref="tcp" port="9000" name = "Two way binary tcp channel">
   <clientProviders>
    <formatter ref="binary"/>
   </clientProviders>
   <serverProviders>
    <formatter ref="binary"/>
   </serverProviders>
  </channel>

以及对于 Zakros

  <channel ref="tcp" port="9000" name = "Two way soap tcp channel">
   <clientProviders>
    <formatter ref="soap"/>
   </clientProviders>
   <serverProviders>
    <formatter ref="soap"/>
   </serverProviders>
  </channel>

请注意,两种服务的传输方式都是 TCP,但 Knossos 的格式为“binary”(二进制),而 Zakros 的格式为“soap”(SOAP)。

接下来是一个可以与 Zakros 和 Knossos 通信的客户端应用程序。以下是
客户端应用程序的通道配置:

对于 Knossos

  <channel ref="tcp" port="8000" name="Two way binary client tcp channel">
   <clientProviders>
    <formatter ref="binary"/>
   </clientProviders>
   <serverProviders>
    <formatter ref="binary"/>
   </serverProviders>
  </channel>

以及对于 Zakros

  <channel ref="tcp" port="8080" name="Two way soap client tcp channel">
   <clientProviders>
    <formatter ref="soap"/>
   </clientProviders>
   <serverProviders>
    <formatter ref="soap"/>
   </serverProviders>
  </channel>

再次请注意,两种服务的传输方式都是 TCP,但格式为二进制和 SOAP。

有一个单独的客户端应用程序必须使用 TCP-binary 通道与 Knossos 通信,并使用 TCP-soap 通道与 Zakros 通信。这就是问题所在。与 Knossos 通过 TCP-binary 通道进行通信将正常工作。但是,与 Zakros 通过 TCP-soap 通道进行通信将无法工作。原因是远程处理系统将从注册通道列表中选择第一个 TCP 通道,而不会
考虑格式接收器。因此,与 Zakros 的连接无法工作,因为第一个 TCP 通道使用二进制格式化程序,而与 Zakros 的连接需要 SOAP 格式化程序。

如果将与 Zakros 的连接配置为 HTTP-soap 通道,一切都会正常工作。但这并不是期望的配置。

一种可能的解决方法是动态插入适当的格式化程序。我们可以通过自定义客户端接收提供程序来实现这一点。以下是类定义。

public class AbstractClientFormatterSinkProvider 
 : IClientFormatterSinkProvider {
 public AbstractClientFormatterSinkProvider() { }
 public AbstractClientFormatterSinkProvider(IDictionary props,
ICollection providerData) { }

 IClientChannelSinkProvider _nextSinkProvider;
 public IClientChannelSinkProvider Next {
  get { return _nextSinkProvider; }
  set { _nextSinkProvider = value; }
 }

 IClientChannelSinkProvider _transportSinkProvider;
 public IClientChannelSink CreateSink(
  IChannelSender channel,
  String URL,
  Object remoteChannelData) {

  // first save the transport sink provider
  if(_transportSinkProvider == null)
   _transportSinkProvider = _nextSinkProvider;

  String format = remoteChannelData as String;
  if(format == null)
   throw new Exception("Client formatter specification required.");

  // create the appropriate formatter sink provider
  IClientChannelSinkProvider  formatterSinkProvider= null;
  if(String.Compare(format,"binary", true) == 0)
   formatterSinkProvider = new BinaryClientFormatterSinkProvider();
  else
  if(String.Compare(format,"soap", true) == 0)
   formatterSinkProvider = new SoapClientFormatterSinkProvider();
  else
   throw new Exception("Channel data required.");

  // insert it between this provider and the transport provider
  formatterSinkProvider.Next = _transportSinkProvider;
  _nextSinkProvider = formatterSinkProvider;

  return formatterSinkProvider.CreateSink(channel, URL, null);
 }
}

为了使远程处理系统接受此客户端通道接收提供程序,必须更改客户端的配置文件,如下所示

<clientProviders>
 <formatter type="RemotingHelper.AbstractClientFormatterSinkProvider,
RemotingHelper"/>
</clientProviders>

这反映了程序集“RemotingHelper.dll”包含类“RemotingHelper.AbstractClientFormatterSinkProvider”

在客户端应用程序内部,连接到服务器 Knossos 和 Zakros 的代码如下:

String urlKnossos = "tcp://knossos:9000/KnossosObject.rem";
KnossosObject objKnossos = (KnossosObject)RemotingServices.Connect(
 typeof(KnossosObject), urlKnossos, "binary");
 
String urlZakros = "tcp://zakros:9000/ZakrosObject.soap";
ZakrosObject objZakros = (ZakrosObject)RemotingServices.Connect(
 typeof(ZakrosObject), urlZakros, "soap"); 

第三个参数“binary”和“soap”作为 remoteChannelData 传递给提供程序的 CreateSink 方法,提供必要的信息以动态插入适当的格式化接收提供程序。

© . All rights reserved.