.NET Romoting 学习总结(四)—— Remoting技术细节之多通道注册

此文章转载自Sharping's Nonsense的http://www.sharping.net/CommentView,guid,9592435d-5496-45f4-a80e-d0a121d454cf.aspx

引言:如果你是一个热爱技术的人,相信看了前面几篇文章后已经迫不及待的去写代码了吧,如果你是一个乐于创新技的术追求者,你一定发现了Rremoting中的一些问题是我没讲到的。细节,又见细节,今天要探讨的就是Remoting中的细节之一——多通道注册的实现。

      常常有这样的需求,我们需要在两个不同的通道完成两种不同的服务,那么回顾一下前面讲的内容,注册通道:
                   
 

TcpChannel channel = new TcpChannel(8080);
ChannelServices.RegisterChannel(channel);


      那么多通道呢?通常的思维模式应该是这样实现:
                    

TcpChannel channel = new TcpChannel(8080);
ChannelServices.RegisterChannel(channel);

TcpChannel channel = new TcpChannel(9999);
ChannelServices.RegisterChannel(channel);

     
      结果出忽意料,这样的语句在运行时检查时候会出问题,编译可以通过。
      通过查阅相关资料,发现,Remoting用来区分通道的标识是来自TcpChannel的Name属性而并不是端口号,也就是说每个通道必须有不同的Name属性,这样理论上可以在创建TcpChannel实例后对其Name属性赋值再进行注册。可是在MSDN上查看TcpChannel类的Name属性原形发现这个Name属性只有get访问器,也就是说他是只读的。晕了吧~~~看来问题还要继续往上追溯。
      通过查阅MSDN可以发现,其实TcpChannel有三种重载构造方法。其中一种就是我们上面的形式,还有不指定端口的,最后还有一种参数很多,我们来看看他的原形:


public TcpChannel(
IDictionary properties,
IClientChannelSinkProvider clientSinkProvider,
IServerChannelSinkProvider serverSinkProvider
);

      参数说明:
      properties           
      保存当前信道配置信息的信道属性的 IDictionary。 
      clientSinkProvider 
      IClientChannelSinkProvider,它为远程处理消息所流过的基础 TcpClientChannel 创建客户端信道 接收。 
      serverSinkProvider 
        IServerChannelSinkProvider,它为远程处理消息所流过的基础 TcpServerChannel 创建服务器信道接收。    

      如果你有好的编程习惯的话会知道,I打头的类型是接口类型。通过查阅资料可以知道,在.NET里Hashtable类是实现了IDictionary接口的,BinaryClientFormatterSinkProvider类实现了IClientChannelSinkProvider 接口,而 BinaryServerFormatterSinkProvider类实现了IServerChannelSinkProvider接口,至于后面两个类,可以使用构造默认构造方法来创建实例,把这两个实例做为后面两个参数即可,因为他们只是提供二进制格式化接收程序,关于这方面细节可以查阅MSDN,通道的属性主要依靠第一个参数IDictionary来区别。
       
      我们来看看Hashtable类,在MSDN里是这样描述他的:表示键/值对的集合,这些键/值对根据键的哈希代码进行组织。键?值?听起来是不是很象数据库里的术语,对,其实他们在某种程度上是同一概念。所谓键,可以理解成字段,值可以理解成这个字段的Value(又想不到词了,只能用E文解释中文)。其实他的实现原理是Hashtable类为我们提供了一个返回类型和参数类型都是string类型的索引器,这样可以自己创建一些键/值对,那么想一想,TcpChannel类的Name属性是不是这样对应的一个Name对应一个字符串(string类型),这里Name就是键,而这个字符串就是值。另外TcpChanne类当然还少不了他的port属性。那么这样创建Hashtable类的实例:

     

Hashtable instance = new Hashtable();
tcpProp["name"] = "tcp9090";
tcpProp["port"] = 9090;


     上面说过 Hashtable 类实现了IDictionary接口,那么程序就因该是这样:

    

IDictionary iChannel = new Hashtable();
tcpProp["name"] = "tcp9090";
tcpProp["port"] = 9090;

   
     这样就构造出了第一个参数,那么多通道问题就可以解决了。我们来看完整代码,注册一个http通道和一个tcp通道.

     注册Tcp通道:

      

IDictionary tcpProp = new Hashtable();
tcpProp["name"] = "tcp9090";
tcpProp["port"] = 9090;
IChannel channel = new TcpChannel(tcpProp,
new BinaryClientFormatterSinkProvider(),
new BinaryServerFormatterSinkProvider());
ChannelServices.RegisterChannel(channel);



      注册Http通道:


     

IDictionary httpProp = new Hashtable();
httpProp["name"] = "http8080";
httpProp["port"] = 8080;
IChannel channel = new HttpChannel(httpProp,
new SoapClientFormatterSinkProvider(),
new SoapServerFormatterSinkProvider());
ChannelServices.RegisterChannel(channel);


      问题到这里算解决了,但是,我觉得有必要研究清楚最开始我们的代码出了什么问题。

     

TcpChannel channel = new TcpChannel(8080);
ChannelServices.RegisterChannel(channel);


       这样的注册方式只改变端口参数为什么无法实现多通道呢?原来 new TcpChannel(8080)方式创建的TcpChannel实例的Name属性默认为"tcp",而以new HttpChannel(8080)方式创建的HttpChannel实例其Name属性为"http",那么两个通道名称都是"tcp"这样就违反了通道名作为区别通道标识的原则,当然就失败了。清楚了,文章完。


      篇外: 有句话说的好:"细节决定成败!" 细节其实往往是学习中最难掌握的,如果说高手和菜鸟的区别主要在编程思想的话,那么可以这么说,高手和菜鸟在编程技术上的区别主要是在细节的掌握上,掌握细节,那么你也算个“小高手”。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值