设为首页 - 加入收藏
广告 1000x90
您的当前位置:78345黄大仙救世网24码 > 接口程序集 > 正文

分离服务程序实现(Net Remoting学习三)

来源:未知 编辑:admin 时间:2019-06-07

  客户应用程序 仍然需要引用 服务程序集(ServerAssembly),因为它需要DemoClass的元信息来创建代理。使用这种共享服务程序集的方式构建Remoting程序,其运行时的示意图如下所示:

  可以看到 宿主应用程序域(Host App Domain,位于服务端) 和 客户应用程序域(Client App Domain,位于客户端)均引用了ServerAssembly服务程序集。尽管直接将服务程序集交给客户端是最简单直接的方法,但是很多情况下,出于安全性或者其他方面考虑,我们并不愿意将服务程序集交给客户端,此时通常有下面几种做法:

  使用接口分离程序集是最简单的一个方法。大家知道接口的作用之一就是将类型的定义和类型的实现分离,放到这里换个说法,就是将类型的元信息和类型的实现分离。具体的步骤如下:

  除此以外,需要传值封送到客户端的对象,比如DemoCount,也要放到ShareAssembly中。原因很简单,在传值封送之后,它便运行于客户端,所以客户端需要它的实现。

  NOTE:注意这里如果不仔细容易看错,因为Server和Share都是S开头,不仔细看两个单词容易搞混。

  然后,取消客户端ClientConsole项目对ServerAssembly的引用,添加它对ShareAssembly项目的引用。然后让服务端ServerConsole项目添加对ShareAssembly项目的引用,通过上面这种方式,现在服务端和客户端运行时的示意图如下所示:

  最后,我们还需要修改客户应用程序的代码,因为它没有引用ServerAssembly,所以不包含DemoClass的元信息,进而我们无法通过 new 来创建DemoClass对象:

  我们也无法直接new一个接口类型IDemoClass,所以我们只能使用上一节提到的Activator类型的GetObject()来创建对象(实为代理):

  然后我们再进行一下测试。我们先运行服务端,它现在可以使用Singleton或者Single Call方式为客户端提供远程服务。再运行一下客户端程序,应该可以获得预期的输出:

  但是使用接口分离程序集的方式无法创建 客户激活对象。因为Activator.GetObject()方法只适用于服务激活方式。而使用Activator.CreateInstance()方法时,作为参数的Type对象需要满足两个条件:1.类型必须继承自MarshalByRefObject;2.服务端必须对此类型进行注册。而使用接口分离服务程序集时,我们在客户端只有一个IDemoClass接口。它的类型信息(type对象,使用typeof(IDemoClass)获得)无法满足CreateInstance()方法中参数的要求。

  如果服务端采用客户激活方式,我们可以采用其他方法获得远程对象,比如下面的 使用“空类”分离服务程序集。

  使用空类分离服务程序集还是利用了客户端只需要类型信息创建代理,而不需要实际的实现代码这个特性。既然如此,我们何不创建两份ServerAssembly,一份包含服务对象的具体实现,供服务端使用;一份不包含服务对象实现,供客户端使用。我们把不包含实现的ServerAssembly版本交给客户端就可以了。接下来我们来一步步看如何实现:

  1.首先,我们在ServerAssembly中再添加一个DemoClass类型,这个类与DemoClass的接口完全一致,区别是它的所有方法、属性都不包含实现,只是抛出异常:

  然后我们注释掉之前包含实现的DemoClass(包含两个DemoClass无法编译),重新成生,得到ServerAssembly.dll文件,将这个文件交给客户端使用。

  3.客户端取消对ServerAssembly项目的引用,将第1步生成的包含DemoClass“空类”的ServerAssembly.dll程序集复制到Bin目录中,然后添加对它的引用。此时客户端的解决方案窗口如下图所示,它不引用其他任何项目,只引用第1步生成的“空类”ServerAssembly程序集:

  这样就完成了所有的步骤,现在我们在客户端再添加一个方法GetClientActivatedObject()方法,获取服务端采用客户激活方式时的远程对象(获取服务激活的方法GetServerActivatedObject()与上一小节中相同):

  注意到在RunTest()方法中,创建对象时调用了GetClientActivatedObject()方法获取了客户激活对象。运行后应该看到一切运转正常,此时的运行方式可以用下图来表示:

  使用“空类”的方式还有一个好处就是可以向Part.2中一样,可以先注册对象,然后直接使用new创建远程对象:

  如果 服务程序集 不大、代码不多的话,使用这种方式或许是最好的办法。但有时服务程序集可能包含大量代码,通过这种方式就显得低效了,我们期望如果能够自动创建一个“空类”程序集,事情就好办的多了。此时,我们可以应用供的Soapsuds.exe工具。

  Soapsuds.exe是.Net所提供的一个工具,它允许客户端通过输入一个远程对象的Url,然后生成一个dll程序集文件,这个文件包含了在客户端创建代理的全部信息但是不包含具体的实现。客户端引用此生成的文件,就如同引用服务程序集一样(你可以将这个文件视为上一小节的“空类”程序集)。因为这个程序集不包含服务对象的实现代码,于是也就达到了向客户端隐藏服务程序实现的目的。需要注意的是,使用Soapsuds.exe获取dll文件时,服务端必须注册为服务激活对象(SingleCall或者Singleton),且使用Http作为传输协议,SOAP作为传输格式。在获得dll文件以后,不管服务器使用那种协议或者格式,客户都可以访问远程对象。

  NOTE:我发现有的书中说当使用Soapsuds.exe这种方式分离程序集,则服务端只能使用Http通道和SOAP格式提供远程服务。我认为这是一个误导,这个限制条件应该是针对于Soapsuds.exe这个工具,而不是你的Remoting程序。你完全可以在服务器端同时开启Http通道和Tcp通道,然后让客户端使用Soapsuds.exe 和 Http通道获得生成文件。而在获得以后使用Tcp通道和Binary格式与服务端进行交互。下面的例子就将使用这种做法。

  1. 首先看服务端,我们要开启Http通道并且以SOAP作为传输格式,应该记得Http通道的默认格式就为SOAP,所以我们只需要开启Http通道就可以了。而我们从Part.2开始就一直使用的RegisterChannel()方法本身就包含了两种通道的注册,这里我再把它复制下来:

  2.我们需要注册服务激活对象,因为服务端只会为服务激活对象产生WSDL文件,所以Soapsuds.exe只能基于服务激活对象生成dll文件。为了后面客户端的测试方便,我们同时在服务端注册服务激活对象和客户激活对象:

  3.现在服务端的设置已经完成,我们来生成客户端要使用的dll文件。打开VS2008 命令提示符,然后在其下输入:

  这将为我们在E盘的根目录下生成ClientProxy.dll文件,这个文件将用于客户端成生代理。

  注意到我们已经在服务端同时开启了 服务激活 和 客户激活,所以我们只需要在上面的RunTest()中切换获取对象的方式就可以对服务激活方式和客户激活方式进行测试。另外看到在GetServerActivatedObject()和GetClientActivatedObject()方法中,我们均使用了tcp协议和8501端口来获取远程对象。而获得ClientProxy.dll生成文件时,使用的是 http协议和8502端口,可见没有对我们的Remoting程序产生影响。

  接下来我们看最后一种实现分离的方式,使用工厂方法实现分离,它属于使用接口分离的一个变种:

  使用工厂方法有一定的局限性,因为它只适用于客户激活方式,但是在表现形式上又像服务激活一样。现在我来详细解释一下,它的做法是将服务对象作为工厂类以服务激活方式(因为是工厂类,所以服务激活方式几乎总是采用Singleton方式)向客户端提供。因为它是服务激活方式,所以我们可以使用本章第一小节分离接口的方式来完成,并使用Activator.GetObject()方法获得。而工厂方法的返回值,为实际向客户端提供服务的对象(DemoClass)的接口,在本例中也就是IDemoClass。通过将实际服务对象作为方法的返回值以接口的方式返回到客户端,这样做等于是绕过了本章第一种方法中使用CreateInstance()创建客户激活对象的参数限制问题。实现工厂方法返回值接口的对象当然就是DemoClass了,我们让它继承自MarshalByRefObject,这样它将永远驻留在服务端,而不会传递到客户端去。接下来我们来一步步实现:

  1.我们先创建一个ShareAssembly项目,这个项目将由服务端和客户端共享,它包含工厂类和实际提供服务的对象(DemoClass)的接口定义,以及进行传值封送的DemoCount结构:

  注意GetDemoClass()方法会为每一个调用此方法的客户端在服务端创建一个DemoClass对象,就相当于直接使用客户激活方式一样。而实际我们直接提供给客户端的ServerFactory是服务激活Singleton方式的。通过这种方式间接的为每个客户端创建了一个DemoClass对象。

  remoting基础      一种分布式处理方式,可以说是DCOM的一种升级      跨过应用程序域,与另外的应用程序域进行通信,即穿越边界      在remoting中是通过通道(channe...博文来自:Peter-H

  1系统设计.NET Remoting是一个丰富的、可扩展的框架,它使得处于不同AppDomain、不同过程和不同机器上的对象可以实现无缝通信。.NET Remoting提供的编程模型和运行时支持功能强大而又易于使用,能够实现透明的交互操作...

  使用.NET Remoting从服务器主动发出事件通知客户端(远程广播) 经常看见有人问:使用.NET Remoting如何从服务器主动发出事件通知客户端?的确,初接触.NET Remoting的人多半会有这样的疑问,因为大部分的文章...

本文链接:http://acrylinkg.com/jiekouchengxuji/149.html

相关推荐:

网友评论:

栏目分类

现金彩票 联系QQ:24498872301 邮箱:24498872301@qq.com

Copyright © 2002-2011 DEDECMS. 现金彩票 版权所有 Power by DedeCms

Top