Remoting 学习之基础篇

以前只是知道有这个东西,没怎么去研究,近段时间公司要求我们好好的学习哈,通过查找资料和总结写点入门及的东西,希望对所有的初学者有点点帮助:
关于WEB服务和Remoting 的讨论简直太多了,简单几句可以大概的说明点他们之间的区别,碰巧今天Leon zhu 也问到了我,当时有点慌没怎么说个明白^_^!!下面说哈实现分布式系统架构的两个方案:
WEB服务当然是一个好东西了,可以跨语言,跨平台,internet访问,但是其弱点就是速度相对较慢,如果我们的分布式应用程序仅仅限于企业内部的话,Remoting是最佳选择!
默认情况下,CLR为我们创建的实例是不能跨APPDOMAIN(每个应用程序都有一个自己的边界)访问的。
对象的序列化:把我的对象的所有信息保存到一个文件系统或一些流媒体里面去。当需要使用的时候,在把他们恢复回来继续使用。这种方式适合对象的拷贝方式。具体实现为:在需要序列化的对象上添加SerializableAttribute属性或者直接实现ISerializable接口也可以。这种方法当对象很大时,其网络开销很大,不太适合。当想通过引用也就是代理的方式来访问远程对象的话可以使用,通过客户端的一个代理来进行消息的转发(表面上看代理和远程对象具有一样的功能实际上他只是负责消息的转发而已,把客户端的消息转发给远程对象或者把远程对象的返回消息转发给客户端,所以大大的提高了速度)所以在进行分布式开发时多采用这种引用的方式(其实我之前一直有过这样的疑问?使一个对象可以远程化有多种方式啊,为什么看到的都是继承自MarshalByRefObject)要实现Remoting ,客户端必须能连接到远程组件所在的服务器,而服务器需要探听来自客户端的请求通道(TCP/THHP/自定义的通道),必须告诉客户端提供了什么服务。而客户端必须连到服务器以请求某个具体的服务
在服务器端需要做什么事情呢?
总的来说要做三件事情,首先要提供一些程序集(远程对象想来请求我这个对象的时候,继承自MarshalByRefObject就可以了);要有一个宿主应用程序(来探听客户端的连接请求,谁连接了,请求的什么服务,以告诉程序集来创建一个实例为其提供服务)可以用IIS/wondows serivce/控制台做为宿主应用程序。
服务器端的应用程序怎么样来设计和实现?
设计的时候需要考虑的问题:
选择在那一个通道来探听客户端的请求;
选择那种激活模式(服务器端/客户端);
客户端怎么样来得到远程对象的元数据的类型(把远程对象的程序集发送到客户端/设计一个接口,把其发到客户端)
实现时需要考虑的问题:
选择什么作为宿主;
注册什么通道
怎么样注册一个通道?
ChannelServices.RegisterChannel (new HttpChannel()); ChannelServices.RegisterChannel (new TcpChannel(4242));
说明:可以同时注册多个通道,在使用时可以根据情况选择,如:在内部网的时候可以使用TcpChannel,在外网则可以通过TcpChannel来实现。
关于激活模式:
服务器端激活模式是有服务器来负责远程对象生命周期的管理的
WellKnownObjectMode.SingleCall 模式,与webserice的激活模式是一样的,每次客户端发出一个请求,服务器端都创建一个实例,其生命周期只局限在函数调用的内部(当函数被调用完后,这个对象就被垃圾回收了)适合无状态的应用程序。
WellKnownObjectMode.Singleton
与SingleCall很大的不同,始终只创建一个远程对象的实例(在系统初使化的时候回第一个请求来的时候会创建此实例,其生命周期一直保存下去。直到宿主应用程序关闭为止)适合有状态的应用程序。
宿主应用程序的一个完整例子:
using System; using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
 using System.Runtime.Remoting.Channels.Http;
 using System.Runtime.Remoting.Channels.Tcp;
 class RemotingHost {  
static void Main(string[] args)
{    
RemotingConfiguration.ApplicationName = "NeweggService"; 
WellKnownServiceTypeEntry newegg=new WellKnownServiceTypeEntry(typeof(Newegg.Accounting),                                        "Accounting",WellKnownObjectMode.Singleton);     RemotingConfiguration.RegisterWellKnownServiceType(newegg);
ChannelServices.RegisterChannel(new HttpChannel(8888));
ChannelServices.RegisterChannel(new TcpChannel(9999));
Console.ReadLine();
  }
}

远程配制文件
配制文件是一个XML文件,
<configuration>
  <system.runtime.Remoting>
      <application name="NeweggService">
          <service>      
             <wellknown mode="SingleCall" type="Newegg.Accounting,Newegg" objectUri =                 "neweggCall" />
            <wellknown mode="Singleton" type="Newegg.Accounting,Newegg" 
                                   objectUri = "neweggTon" />
         </service>  
    <channels>
    <channel port="8888" ref="http" />
    <channel port="9999" ref="tcp" />
    </channels>
     </application>
   </system.runtime.Remoting>
</configuration>
使用配置文件:
using System;
using System.Reflection;
using System.Runtime.Remoting;
class RemotingHost
{  
static void Main(string[] args)
 {
    String s = Assembly.GetExecutingAssembly().Location; 
   RemotingConfiguration.Configure (s + ".config"); 
   Console.ReadLine(); 
 }
}
client activation
是基于租界的生命周期管理。每一个客户端激活的对象都有一个默认的租界期(也可以重新配置),如在默认的租界期内没有续租,服务器上的对象就回被回收掉。只要客户端在调用远程对象,其租界期永远是最新的。如过在租界期内,客户端调用完毕,则服务器端对象也自动释放。
程序化的一个客户端激活的例子?
class RemotingHost
{  
static void Main(string[] args)
 {    
       RemotingConfiguration.ApplicationName = "NeweggService";            ActivatedServiceTypeEntry newegg = new ActivatedServiceTypeEntry(typeof(Newegg.Acounting));
     RemotingConfiguration.RegisterActivatedServiceType(newegg)
    ChannelServices.RegisterChannel(new HttpChannel(8888));
 ChannelServices.RegisterChannel(new TcpChannel(9999));
     Console.ReadLine();
  }
}
客户端激活模式配置文件的格式
<configuration>
   <system.runtime.Remoting>
     <application name="NeweggService">
       <service>
         <activated type="Newegg.Acounting,Acounting" />              </service>
       <channels>
         <channel port="8888" ref="http" />
         <channel port="9999" ref="tcp" />
       </channels>
     </application>
   </system.runtime.Remoting>
 </configuration>

class RemotingHost
 {
   static void Main(string[] args)
   {
     String s = Assembly.GetExecutingAssembly().Location;          RemotingConfiguration.Configure (s + ".config");
     Console.ReadLine();
   }
 }
客户端怎么请求远程对象的服务(服务器端激活时)?
使用 Activator.GetObject()一个远程对象的代理就会自动下载到你的客户端来,然后在进行通信,也可以用通过NEW这个方法来实现(要看代理类的元数据是什么格式,如果是直接将DLL发送到客户端则可以使用NEW,如果是接口则不行)。
客户端怎么请求远程对象的服务(客户端激活时)?
使用Activator.CreateInstance()一个远程对象的代理就会自动下载到你的客户端来,然后在进行通信,也可以用通过NEW这个方法来实现(要看代理类的元数据是什么格式,如果是直接将DLL发送到客户端则可以使用NEW,如果是接口则不行)。。。。睡觉了~~~!
 


 

posted on 2006-03-02 23:47  kim  阅读(1818)  评论(3编辑  收藏  举报

导航