Dotnet中 Remoting技术 简明扼要的介绍 2 - 3
六、激活模式 (Activation requests)
(一) 服务器端2种
1. SingleCall(单调用)
对于客户端的每一个代理类的函数调用都产生一个组件服务对象,当函数调用结束后,对象销毁。
(Web服务器实际就是这种SingleCall方式)
对于每一个客户端的函数调用都会产生一个服务组件对象。此对象的生命周期是该客户端函数范围,也就是说调用结束后就销毁该对象。
使用情形:
适合没有状态的应用程序。 比如 一个客户代理有两个方法都操作同一个变量 i, 首先把 i的值改成100, 然后用另一个方法去取值, 得到的还是默认值,因为2个方法调用的 是 不同对象。
负载平衡性比较好, 用到创建,不用时马上销毁。
2. Singleton(单件)
使用只有一个 远程范围对象 实例,当应用程序启动或者第一此调用时候创建。 任何时候就只有1个对象在提供服务。 这个时候就可以保存状态信息。
使用情形:
对象构造过程非常耗时。
需要保存程序执行状态的情况下。
       完全编程方式编写宿主:
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          //提供的远程组件的服务的名字。         RemotingConfiguration.ApplicationName = "WiseOwlMathService";         WellKnownServiceTypeEntry WKSTE = new WellKnownServiceTypeEntry(             typeof(WiseOwl.Calculator),     //服务对象             "SharedCalc",                   //客户端请求名,也就是请求入口             WellKnownObjectMode.Singleton   //激活模式(单调用SingleCall、单件Singleton)             );         RemotingConfiguration.RegisterWellKnownServiceType(WKSTE);         //在HTTP9000端口TCP4242端口监听请求,客户端可以通过种方式请求。         ChannelServices.RegisterChannel(new HttpChannel(9000));         ChannelServices.RegisterChannel(new TcpChannel(4242));         Console.ReadLine();}} /* 客户端调用方式  * ProtocolScheme://ComputerName:Port/PossibleApplicationName/ObjectUri  *  PossibleApplicationName - 此处应该填:"WiseOwlMathService"  *  ObjectUri               - 此处应该填:"SharedCalc"  *   * 如果是以IIS作为宿主,则PossibleApplicationName为虚拟目录名,ObjectUri必须以.rem/.soap结尾 */
 
 
fileName : testServerHost.exe.config <configuration>   <system.runtime.remoting>     <!--服务名-->     <application name="WiseOwlMathService">       <service>         <!--         wellknown 译 “众所周知”         也就是服务器激活模式,因为服务器控制一切,所有的调用都要取决于服务器。                  此处配置为同时提供2种服务器激活模式。         可以在客户端请求的时候提供 不同的URI                              来使用 不同的激活模式。         -->         <wellknown mode="SingleCall" type="WiseOwl.Calculator,MathObjects" objectUri = "EphemeralCalc" />         <wellknown mode="Singleton" type="WiseOwl.Calculator,MathObjects" objectUri = "SharedCalc" />       </service>       <channels>         <channel port="9000" ref="http" />         <channel port="4242" ref="tcp" />       </channels>     </application>   </system.runtime.remoting> </configuration>  fileName : testServerHost.exe using System; using System.Reflection; using System.Runtime.Remoting; class RemotingHost {     static void          String s = Assembly.GetExecutingAssembly().Location;          RemotingConfiguration.Configure(s + ".config");          Console.ReadLine();      } }
 
 
(二) 客户端1种
1. Client activated object (CAO)
提供多种 组件服务器对象生命周期 管理方式:
1 创建客户代理类的实例 就产生对应的 服务器 组件服务器对象, 客户代理类销毁,服务器销毁。
2 租借机制, 创建客户端代理类实例并不是创建,而是向服务器租借对象。到期如果不续租,就销毁了。(可以防止客户端忘记销毁代理类实例所引发服务器资源浪费)
       完全编程方式:
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          RemotingConfiguration.ApplicationName = "WiseOwlMathService";         //ActivatedServiceTypeEntry : 表示客户端激活类型         //服务器端激活对应为WellKnownServiceTypeEntry         ActivatedServiceTypeEntry ASTE = new ActivatedServiceTypeEntry(typeof(WiseOwl.Calculator));         //RegisterActivatedServiceType()方法表示注册一个客户端激活的服务,          //服务器端激活类型的服务注册对应的方法是:RegisterWellKnownServiceType()         RemotingConfiguration.RegisterActivatedServiceType(ASTE);         ChannelServices.RegisterChannel(new HttpChannel(9000));         ChannelServices.RegisterChannel(new TcpChannel(4242));         Console.ReadLine();}} /* 客户端调用方式(无URI)  *  ProtocolScheme://ComputerName:Port/PossibleApplicationName  */
 
 
使用配置文件方式:
fileName : testServerHost.exe.config <configuration>   <system.runtime.remoting>     <application name="WiseOwlMathService">       <service>         <!--         activated 客户端激活         wellknown 服务器端激活         -->         <activated type="WiseOwl.Calculator,MathObjects" />       </service>       <channels>         <channel port="9000" ref="http" />         <channel port="4242" ref="tcp" />       </channels>     </application>   </system.runtime.remoting> </configuration> fileName : testServerHost.exe   //服务器端激活和客户端激活,完全一样 using System; using System.Reflection; using System.Runtime.Remoting; class RemotingHost {     static void          String s = Assembly.GetExecutingAssembly().Location;          RemotingConfiguration.Configure(s + ".config");          Console.ReadLine();      } }
 
 
七、Remoting clients 远程处理的客户端编写。
(一) 调用 服务器端激活 的远程对象
1. 可以使用Activator.GetObject(类型, URL); 获取远程代理类的对象。
using System;using System.Runtime.Remoting;using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Http;using System.Runtime.Remoting.Channels.Tcp; class RemotingClient{     static void          //客户通过http通道和服务器联系          //此处new HttpChannel()不需要写端口号,因为Machine.config中已经设置的有默认端口。         ChannelServices.RegisterChannel(new HttpChannel());         // Connect to a Well-known object              string uriWKO = "http://localhost:9000/WiseOwlMathService/SharedCalc";         object o = Activator.GetObject(typeof(WiseOwl.Calculator), uriWKO);         // Use the Calculator            WiseOwl.Calculator c;         c = o as WiseOwl.Calculator;         c.Add(21); }}
 
 
2. 也可以使用New , 如果传递给客户端的元数据不是接口组件,而是整个服务组件,则可以new,否则只能用上面的方法
(二) 调用 客户端激活 的远程对象
1. 可以使用Activator.CreateInstance()方法。获取远程代理类的对象。
using System;using System.Runtime.Remoting;using System.Runtime.Remoting.Activation; using System.Runtime.Remoting.Channels;using System.Runtime.Remoting.Channels.Http; using System.Runtime.Remoting.Channels.Tcp; class RemotingClient{      static void           //客户通过http通道和服务器联系            ChannelServices.RegisterChannel(new TcpChannel());          // Connect to a Well-known object               string url = "tcp://localhost:4242/WiseOwlMathService";                  object[] activationAttributes = new object[]{new UrlAttribute(url)};          object o = Activator.CreateInstance(typeof(WiseOwl.Calculator),null,activationAttributes);          // Use the Calculator             WiseOwl.Calculator c;          c = o as WiseOwl.Calculator;          c.Add(21);        }}
 
 
2. 也可以使用New, 如果传递给客户端的元数据不是接口组件,而是整个服务组件,则可以new,否则只能用上面的方法
八、客户端调用也可以使用 配置文件
fileName : testServerCall.exe.config <configuration>   <system.runtime.remoting>     <application name="WiseOwlMathService">       <client url = "http://localhost:9000/WiseOwlMathService" displayName = "WiseOwlMathService">         <!--客户端激活-->         <activated type = "WiseOwl.Calculator,MathObjects"/>         <!--服务器端激活-->         <wellknown type = "WiseOwl.BadCalculator,MathObjects" url="http://localhost:9000/WiseOwlMathService/BadCalc"/>       </client>     </application>   </system.runtime.remoting> </configuration> fileName : testServerCall.exe using System;using System.Runtime.Remoting;using System.Runtime.Remoting.Activation; using System.Runtime.Remoting.Channels;using System.Runtime.Remoting.Channels.Http; using System.Runtime.Remoting.Channels.Tcp; class RemotingClient{      static void           string s = System.Reflection.Assembly.GetExecutingAssembly().Location;         System.Runtime.Remoting.RemotingConfiguration.Configure(s + ".config");          //使用配置文件且读入配置后,就可以直接new对象。但new的前提是客户端有完整的服务元数据,也就是不是接口。当然也应该还是可以不new的。这个地方虽然是new,但还是获得的远程对象。          WiseOwl.Calculator c = new WiseOwl.Calculator();          c.Add(21);          WiseOwl.BadCalculator b = new WiseOwl.BadCalculator();          b.Add(21);             }}