一步一步学Remoting收藏一步一步学Remoting之一:从简单开始一、Remoting的优缺点?优点:1、能让我们进行分布式开发2、Tcp通道的Remoting速度非常快3、虽然是远程的,但是非常接近于本地调用对象4、可以做到保持对象的状态5、没有应用程序限制,可以是控制台,winform,iis,windows服务承载远程对象缺点:1、非标准的应用因此有平台限制2、脱离iis的话需要有自己的安全机制二、Remoting和Web服务的区别?ASP.NETWeb服务基础结构通过将SOAP消息映射到方法调用,为Web服务提供了简单的API。通过提供一种非常简单的编程模型(基于将SOAP消息交换映射到方法调用),它实现了此机制。ASP.NETWeb服务的客户端不需要了解用于创建它们的平台、对象模型或编程语言。而服务也不需要了解向它们发送消息的客户端。唯一的要求是:双方都要认可正在创建和使用的SOAP消息的格式,该格式是由使用WSDL和XML架构(XSD)表示的Web服务合约定义来定义的。.NETRemoting为分布式对象提供了一个基础结构。它使用既灵活又可扩展的管线向远程进程提供.NET的完全对象语义。ASP.NETWeb服务基于消息传递提供非常简单的编程模型,而.NETRemoting提供较为复杂的功能,包括支持通过值或引用传递对象、回调,以及多对象激活和生命周期管理策略等。要使用.NETRemoting,客户端需要了解所有这些详细信息,简而言之,需要使用.NET建立客户端。.NETRemoting管线还支持SOAP消息,但必须注意这并没有改变其对客户端的要求。如果Remoting端点提供.NET专用的对象语义,不管是否通过SOAP,客户端必须理解它们。三、最简单的Remoting的例子1、远程对象:建立类库项目:RemoteObjectusingSystem;namespaceRemoteObject{publicclassMyObject:MarshalByRefObject{publicintAdd(inta,intb){returna+b;}}}2、服务端建立控制台项目:RemoteServerusingSystem;usingSystem.Runtime.Remoting;namespaceRemoteServer{classMyServer{[STAThread]staticvoidMain(string[]args){RemotingConfiguration.Configure(RemoteServer.exe.config);Console.ReadLine();}}}建立配置文件:app.configconfigurationsystem.runtime.remotingapplicationname=RemoteServerservicewellknowntype=RemoteObject.MyObject,RemoteObjectobjectUri=RemoteObject.MyObjectmode=Singleton//servicechannelschannelref=tcpport=9999//channels/application/system.runtime.remoting/configuration3、客户端:建立控制台项目:RemoteClientusingSystem;namespaceRemoteClient{classMyClient{[STAThread]staticvoidMain(string[]args){RemoteObject.MyObjectapp=(RemoteObject.MyObject)Activator.GetObject(typeof(RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings[ServiceURL]);Console.WriteLine(app.Add(1,2));Console.ReadLine();}}}建立配置文件:app.config一步一步学RemotingRemotingRemotingRemoting之二:激活模式远程对象的激活模式分服务端激活和客户端激活两种,(也就是对象分服务端激活对象或者说是知名对象和客户端激活对象两种)先看看msdn怎么描述服务端激活的:服务器激活的对象是其生存期由服务器直接控制的对象。服务器应用程序域只有在客户端在对象上进行方法调用时才创建这些对象,而不会在客户端调用new或Activator.GetObject时创建这些对象;这节省了仅为创建实例而进行的一次网络往返过程。客户端请求服务器激活的类型实例时,只在客户端应用程序域中创建一个代理。然而,这也意味着当您使用默认实现时,只允许对服务器激活的类型使用默认构造函数。若要发布其实例将使用带参数的特定构造函数创建的类型,可以使用客户端激活或者动态地发布您的特定实例。一步一步学RemotingRemotingRemotingRemoting之四:承载方式(1)(1)(1)(1)在实际的应用中我们通常只会选择用windows服务和iis来承载远程对象。选择windows服务的原因是能自启动服务,服务器重启后不需要再去考虑启动service。选择iis的理由是我们能使用集成验证等一些iis的特性。在msdn中可以找到相关文章:://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cpguide/html/cpconRemotingExampleHostingInIIS.asp可能大家会觉得这个过程将是一个复杂的过程,其实不然,下面说一下实现方法,步骤非常少。先来建立远程对象一步一步学RemotingRemotingRemotingRemoting之四:承载方式(2222)这里来说一下iis承载方式,顺便简单说一下remoting的通道和【复杂对象】中的遗留问题。首先明确一点:iis来承载的话只能是http通道方式的。我们来建立一个web项目,比如叫remoting,删除项目中的所有webform,把远程对象dll-RemoteObject.dll复制到项目的dll文件夹下面,然后打开web.config进行服务端设置:configurationappSettingsaddkey=ServiceURLvalue=tcp://localhost:9999/RemoteObject.MyObject//appSettings/configuration4、测试在最后编译的时候会发现编译报错:1、找不到app.Add()2、找不到RemoteObject这是因为客户端RemoteClient没有添加RemoteObject的引用,编译器并不知道远程对象存在哪些成员所以报错,添加引用以后vs.net会在客户端也保存一个dll,可能大家会问这样如果对远程对象的修改是不是会很麻烦?其实不麻烦,对项目编译一次vs.net会重新复制dll。然后直接运行客户端会出现“目标主机拒绝”的异常,也说明了通道没有打开运行服务端再运行客户端出现“找不到程序集RemoteObject”!回头想想可以发现我们并在服务端对RemoteObject添加引用,编译的时候通过是因为这个时候并没有用到远程对象,大家可能不理解运行服务端的时候也通过?这是因为没有这个时候还没有激活远程对象。理所当然,对服务端要添加引用远程对象,毕竟我们的对象是要靠远程承载的。现在再先后运行服务端程序和客户端程序,客户端程序显示3,测试成功。四、结束语我们通过一个简单的例子实现了最简单的remoting,对其实质没有做任何介绍,我想通过例子入门才是最简单的。服务器激活的对象有两种激活模式(或WellKnownObjectMode值):Singleton和SingleCall。Singleton类型任何时候都不会同时具有多个实例。如果存在实例,所有客户端请求都由该实例提供服务。如果不存在实例,服务器将创建一个实例,而所有后继的客户端请求都将由该实例来提供服务。由于Singleton类型具有关联的默认生存期,即使任何时候都不会有一个以上的可用实例,客户端也不会总接收到对可远程处理的类的同一实例的引用。SingleCall远程服务器类型总是为每个客户端请求设置一个实例。下一个方法调用将改由其他实例进行服务。从设计角度看,SingleCall类型提供的功能非常简单。这种机制不提供状态管理,如果您需要状态管理,这将是一个不利之处;如果您不需要,这种机制将非常理想。也许您只关心负载平衡和可伸缩性而不关心状态,那么在这种情况下,这种模式将是您理想的选择,因为对于每个请求都只有一个实例。如果愿意,开发人员可以向SingleCall对象提供自己的状态管理,但这种状态数据不会驻留在对象中,因为每次调用新的方法时都将实例化一个新的对象标识。首先对于服务端激活的两种模式来做一个试验,我们把远程对象做如下的修改:usingSystem;namespaceRemoteObject{publicclassMyObject:MarshalByRefObject{privateinti=0;publicintAdd(inta,intb){returna+b;}publicintCount(){return++i;}}}对客户端做以下修改:RemoteObject.MyObjectapp=(RemoteObject.MyObject)Activator.GetObject(typeof(RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings[ServiceURL]);Console.WriteLine(app.Count());Console.ReadLine();第一次打开客户端的时候显示1,第二次打开的时候显示2,类推……由此验证了Singleton类型任何时候都不会同时具有多个实例。如果存在实例,所有客户端请求都由该实例提供服务。如果不存在实例,服务器将创建一个实例,而所有后继的客户端请求都将由该实例来提供服务。把服务器端的config修改一下:wellknowntype=RemoteObject.MyObject,RemoteObjectobjectUri=RemoteObject.MyObjectmode=SingleCall/(这里注意大小写,大写的C)再重新运行服务端和客户端,打开多个客户端发现始终显示1。由此验证了SingleCall类型对于每个客户端请求都会重新创建实例。下一个方法调用将由另一个服务器实例提供服务。下面再说一下客户端的激活模式,msdn中这么写:客户端激活的对象是其生存期由调用应用程序域控制的对象,正如对象对于客户端是本地对象时对象的生存期由调用应用程序域控制一样。对于客户端激活,当客户端试图创建服务器对象的实例时发生一个到服务器的往返过程,而客户端代理是使用对象引用(ObjRef)创建的,该对象引用是从在服务器上创建远程对象返回时获取的。每当客户端创建客户端激活的类型的实例时,该实例都将只服务于该特定客户端中的特定引用,直到其租约到期并回收其内存为止。如果调用应用程序域创建两个远程类型的新实例,每个客户端引用都将只调用从其中返回引用的服务器应用程序域中的特定实例。理解一下,可以归纳出1、客户端激活的时间是在客户端请