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); }}