Net C# Remoting 分布技术要点解析

.Net C# Remoting 分布技术要点解析

现学习C#编程,而基础Remoting 是一个非常重要课程,但通俗的介绍的文章很少,故我将这个给大家分享一下:

Remoting 为应用程序间或进程间通讯提供了一种可行的途径。两个进程可以存在于同一台电脑也可以分别存在于连网的局域网或者广域网中的两个不同的计算机上。计算机进程间通讯表面上看起来没什么大不了的,不过,它却有一个相当复杂的过程。以下向你阐述原因。 在任何操作系统中,安全与稳定是两个最重要的目标。实现这两个目标的途径是把每个当前执行的应用程序载入到单独的进程中去。由于这样的设计,应用程序进程彼此隔离,这样,一个进程中的代码就无法访问到另外一个进程中的代码或数据。那样的设计,就强制性地使一个进程不可以也不可能访问到它不被允许触及的资源范围,保证了,安全性的方面的目标实现。另外,这样的设计也通过保证一个问题进程对另外一个进程或者操作系统进程的内存空间不会造成破坏而实现了在稳定方面的目标. .NET FRAMEWORK通过application domains提供了另一种级别的隔离,它授权两个或者更多程序运行在同一进程中,维持着同级别的隔离好像他们是处于各自的进程中,但同时概观上又是一个多进程的整体。进程间隔离的需求是很明显的,然而,却也存在着别外一个事实:进程间通讯有时也是需要的。 对分布式计算与分布式测量的强调与需要变得越来起迫切。.NET FRAME. WORK 框架提供了几种途径来解决进程间通讯这一需求,总起来说,我们说remoting,web services 可能是最广为人知的remoting方式。不过,它们却也不是你的仅有的选择。本文你将会看到.net remoting 技术的概观,这将帮助你选择各种各样的remoting技术实现类型。。    Remoting 在服务端的一个进程里面生成一个可以在客户端的另一个进程里面可编程的对象,这就是marshalling,有两种完全不同的方式来marshal 一个对象;     1.Marshal by value:服务端创建一个对象的copy,并把COPY传递到客户端;‍(服务器端激活方式MBV)     2.Marshal by reference:客户端创建该对象的代码并使用此代理来访问这个对象.‍(客户端激活方式MBR) 当一个客户端发出一个向[mashalled by value(MBV)]对象的请求时,服务端创建一个完全一样的COPY并把这个拷贝传至客户端.客户端就可以直接在客户端自已的进程内或者应用程序域里面使用这个对象的数据与可执行函数体而不需要额外地向服务端发面其它请求。要实现MBV,在你的类里面你必须要么实现ISerializable接口,要么添加<serialazable>属性标记。    与之相对,当一个客户要向一个[marshalled by reference(MBR)]过的对象发出请求的时候,.net frame. 会在客户端就用程序域里创建一个代理,这样客户端就使用这个代码来访问服务端的源对象。要实现MBR,一个类必须最少扩展System.MarshalByRefObject 类,下图展示了MBV与MBR的区别. 有了MBV与MBR的区别,你如何确定什么时间使用哪一种来对远程对象进行编程呢?在某些情况下,你没得选择-你必须用MBR,这样的情况比如:你当一个应用程序组件必须运行在源远程应用程序域内,它要使用服务端的操作系统句柄或者服务端文件,另外当客户端需要了解到服务端的对象中的变化的时候我们也需要用到MBR。当使用MBV的时候Marshalled 过的对象的一份完全一样的被发送到客户端的拷贝是静态的,并不会影响到(/改变)服务端marshalled过的对象的状态。 在很多情况下,MBV 或者MBR都是可行的,问题是哪一个更好呢?这里关心的一点是:带宽.那一种技术对客户机与服务端之间的数据传输方面的需求更少一些呢?MBV(服务器端激活方式)的话,需要一次性地把一个对象拷贝传输到客户端,不过,如果这个对象太大的话,那样就是一个不小的工作量了,在对象拷贝被传送到客户端后,对对象的访问就只限于客户端的应用程序域范围内,完全不需要涉及到传输机制. 相反的,MBR(客户端激活方式)并不需要传送一个对象拷贝到客户端,每次访问对象都需要一个一来一回的数据信息的传送,个人认为少量的请求可能不至于加重了通讯的负载,但是如果客户端发出的请求数以万计的话,这个对带宽的影响由不得你不去考虑.   那么选择基准呢?如果对象数据量比较小而应用程序要频繁访问这样的情况最好呢就是MBV,如果对象数据量比较大而客户机访问服务端次数相对不是很频繁,那就用MBR --------------------------------------------------------------------------    channel是一个实现在应用程序域间客户端对象与服务端对象进行通讯的对象,.net framework 默认实现了以下两种channel: HttpChannel:使用http协议实现地一种通道;  TcpChannel: 使用Tcp协议实现的一种通道. 这两者都是有双重目地的:他们在客户端实现一处通道,用来在客户方与远程服务端对象进行通讯,另在服务端实现一个通道用来在服务端与客户端进行通讯.HttpChannel类使用SOAP协议封装信息,soap协议会把这个通讯内容以XML文件格式进行传输,相应的TchChannel却是使用字节码(二进制)格式地封装这些传输信息.当然,二进制格式较为更高效一些(封装过的数据量更小),而简单的文本形式的soap格式却是更易于在网络安全性能方面要求较高像安装有防火墙这样的环境中等工作.   当你创建一个服务对象-远端对象,你也就为这个对象定义与注册了一个或多个通道,每一个通道有一个特别的端口.通过注册一个通道/接口组合,你告诉了.net infrastructure 来监听通过这个通道的端口以便随时获取请求信息.当一个消息到达里,framework 把它引导到正确的服务端对象,下图展示了客户端与服务端的通讯情况,注意,当你在单独的一个系统里面运用remoting 里,客户端端口号与服务端端口号不可以相同,因为对于一个指定的端口你只可以使用一次. 在客户端你的代码也同样的创建一通道与相应的一个指定的端口,它使用Activator类来获取远程对象的一个引用,这个引用是对(MBV)的对象的引用,或许可能是(通过远程对象的代理MBR)的对象的引用,你可以通过远程对象所在服务器URL,所以类名,和你指定的一个URI来唯一标识一个远程对象,.net infrastructure 会考虑到这些细节--作为一个远程用户,你用不着关心远程服务端对象使用的是MBV还是MBR或者其它方面的东西,在下面的demo程序中,你会发现是如此简单.
--------------------------demo--------------------------------------------

本示例程序展示了一个简单的remoting 例子。他例证了一个基本的任务,它本身涉及创建一个远程类,一个服务端,一个客户端,要使本实例切实可运行,打开vs.net命令行模式,为本项目创建一个文件夹,使文件夹为当前文件夹(意思,应该是cd 到项目所在文件夹). 远程类(RemoteClass)包含一个返回到请求方"secret"字符串的简单方法,类构造函数显示一个console消息当客户端激动了这个类,当然,这里console message 只是一个演示,它并没有存在的必要性。注意,本类唯一的与remoting 相关的一个方面是它继承自MarshalByRefObject.你可以使用任何文件编辑器来创建本DEMO代码然后把它保存到一个项目文件夹下以RemotingClass.cs命名即可。然后,在命令行模式下,以下面命令编译本类(一定要同一行中把命令全部输入进去): csc /t:library /debug /r:System.Runtime.Remoting.dll RemoteClass.cs 这个类就被编译成RemoteClass.dll文件. 然后,你需要创建客户端(Client.cs),用它来调用远程类,它包含以下内容: 1.在端口8084上创建一个TcpChannel, 2.用.net infrastructure 注册本通道, 3.尝试通用调用Activator.GetObject()方法来获取一对远程对象的引用, 4.如果无法获取一个引用,它向用户显示一条信息,如果执行正常,它调用远程对象的SecretWord()方法体并显示返回数据。

    对Activator.GetObject()方法的调用需要一些说明。这个方法接受两个参数,第一个是远程类的类型,你可以通过使用typeof()方法获得和类的名字空间和类名作为参数,第二个参数有以下部分: tcp://:   标识被使用的协方。当然这里指定的是Tcp ,因为客户端与服务端使用TcpChannel来能通讯. localhost: 远程类所在计算机名,本例中,远程类与客户端在同一台机器上,所以是localhost,当然,如果你是在internet 环境中使用,你就你远程计算机名来替代就可以了。 8085: 指定远程类监听的端口, /Secret: 远程类相关的URI,这是一个可以任意起的名称,只要它跟服务端的URI相符就ok.
  编译本客户端,注意:编译器指定一个到你前面创建的RemotingClass.dll的引用. csc /debug /r:remoteclass.ell /r:System.Runtime.Remoting.dll Client.cs    最后,你需要创建服务器,服务器监听客户端的请求,然后连接请求到远程类,下面显示这个类的内容:   1.以端口8085创建一个新的TcpChannel,注意这是客房端寻找远程对象的同一个通道。 2.用.net infrastructure 注册本通道,     3.通过调用RemotingConfiguration.RegisterWellKnownServiceType()方法来注册远程类,参数是: 4.第一个参数标识被注册的类     5.第二个参数为类指定URI,当客户端查找这个类里会用到这个URI,     6.第三个参数指定是否还有没有(从多于一个客户端)发出的其它请求,他们将被类的同一个实类处理; 7.向用户返回一条消息,然后直接用户按Enter中止。   第四个步骤是需要的,因为服务端必须被执行以便正常工作,换句话说,只有服务端程序在运行状态下,才有可能会"监听"来自客户端的请求,     把代码保存为Server.cs并以下面的例行编译它,以完成最后工作. csc /debug /r:remoteclass.dll /r:System.Runtime.Remoting.dll Server.cs    假设所有项目以上三部分都编译成功,你就可以以下面方式来测试本程序: 1. 再打开一个命令行窗口,切入到项目文件夹下,现在,你有两个打开的命令行窗口(这种需要是很明显的) 2. 在一个窗口里面输入Server 来指行server程序,它会显示"Hit<enter> to exit...",这样,本服务端就处于监听状态下,监听来自客户端的请求,  3.在另一个窗口里输入"Client"来执行客户端程序,你会看到有两件事: 4.客户端窗口显示消息"The secret word is REMOTING",然后客户端程序终止, 5.服务端窗口显示消息"MyRemoteClass activated",指示有客户端激活了远程类, 6.要终止server ,切换到server窗口,换enter.   

  好了,一个简单的实现.net framework的remoting 功能的例子就是这样了,不过,很少有现在工作当中的应用程序需求会像本程序这么简单,不过,基本原理是一样的.

posted @ 2013-03-25 22:54  阳光小屋  阅读(551)  评论(0编辑  收藏  举报