Remoting学习二

      .NET Remoting是用来远程调用对象的,何为远程?其实不一定非要在两台相隔千里的机器上。只要是不同应用程序域的对象调用就是属于远程调用。通常源应用程序域就叫做服务器端,本地应用程序域就叫客户端。.NET Remoting大致可以分为三个部分:

     1.宿主应用程序(域),服务程序运行的环境(服务对象所在的AppDomain),它可以是控制台应用程序,Windows窗体程序,Windows 服务,或者是IIS的工作者进程等。上例中为 NewDomain。

     2.服务程序(对象),响应客户请求的程序(或对象),通常为继承自MarshalByRefObject的类型,表现为一个程序集。上例中为 DemoClass。

     3.客户应用程序(域),向宿主应用程序发送请求的程序(或对象)。上例中为 ConsoleApp.exe。

     下面介绍这三个组成部分。

     1.客户端(客户应用程序)

     客户端的处理包含三个基本的组成部分,代理(Proxy)、格式器(Formatter) 和 通道(Channel)。

     客户端总是通过一个代理来和服务端对象进行交互。客户端向代理请求属性或者方法调用,然后代理将请求发送给服务端的对象。每一个代理绑定一个远程对象,多个代理也可以绑定同一个对象(Singleton方式,后面会介绍);客户端的多个对象也可以使用同一个代理。代理分为两部分,一个名为透明代理(Transparent Proxy),一个名为真实代理(Real Proxy)。透明代理提供了和服务对象完全一致的公共接口,当客户进行方法调用时,透明代理将栈帧(Stack Frame,在栈中为参数、返回地址和局部变量保留的一块内存区,必要时在过程调用中使用)转换为消息(Message),然后将消息发送给真实代理。这个消息对象包含了调用的对象的方法信息,包括方法签名、参数等,同时还包括客户端的位置(注意这里,方法回调(Callback)时会再提到)。真实代理知道如何连接远程对象并将消息发送给它。

真实代理收到消息后,请求Formatter 对象对其进行序列化,同时将客户程序中断(block)。.Net 内置了两种序列化格式,一种是二进制Binary,一种是SOAP。Formatter将消息进行序列化之后,然后将其发送到通道中,由通道将消息发送到远程对象。当请求返回时,Formatter将返回的消息反序列化,然后再提交给代理,代理将返回值放到发送请求的客户对象的调用堆栈上,随后将控制返回给客户调用程序(解除中断)。这样就给了客户对象一个错觉:代理即为远程对象。

     2.服务端(宿主应用程序)

     服务端主要由 通道(Channel)、格式器(Formatter)、Stack Builder组成。

     在服务端,宿主程序保持着为Remoting所打开的端口的监听,一旦通道收到消息,它便将消息发送给Formatter,Formatter将消息进行反序列化,然后将消息发送给Stack Builder,Stack Builder读取消息,然后依据消息创建对象(可选),调用方法。方法返回时,Stack Builder将返回值封装为消息,然后再提交给Formatter,Formatter进行格式化之后,发送到通道传递消息。

    3.Remoting对象的三种激活方式

    客户端激活(Client Activated):服务器端为每个客户端连接创建一个对象,注意这里是每个客户端连接,一个客户端连接中可能会有多个Remoting请求。这种情况在客户端比较多,或者是大对象时服务器端负载比较大。

    服务器端激活(Server activated Singleton):这个模式的最大特色就是所有的客户共享同一个对象。服务端只在对象第一次被调用时创建服务对象,对于后继的访问使用同一个对象提供服务。

    服务激活 Single Call(Server activated Single Call):Single Call方式是对每一次请求(比如方法调用)创建一个对象,而在每次方法返回之后销毁对象。由此可见Single Call 方式的最大特点就是 不保存状态。使用Single Call的好处就是不会过久地占用资源,因为方法返回后对资源的占用就随对象被销毁而释放了。最后,Single Call 方式也不允许使用由参数的构造函数。

     4.信道:信道是跨越远程处理边界(无论是在应用程序域、进程还是计算机之间)在应用程序之间传递消息的对象。信道必须实现 IChannel 接口,该接口提供信息性的属性,例如 ChannelNameChannelPriority。这是一个基本的接口。

       而对于发送和接受又分为两种接口:旨在侦听特定端口上的特定协议的信道实现 IChannelReceiver,而旨在发送信息的信道实现IChannelSender接口,这两个接口都实现了IChannel。对于协议分为TcpChannel和HttpChannel,他们都实现了IChannelReceiver和IChannelSender接口。因此TcpChannel和HttpChannel都是实现接受和发送。

     5.对象位置

        在Remoting里,客户端是需要知道远程对象的位置的,就像网页地址一样,远程对象也是需要一个地址。RemotingConfiguration类型还有一个ApplicationName静态属性,当设置了这个属性之后,对于客户激活对象,可以提供此ApplicationName作为Url参数,也可以不提供。如果提供ApplicationName,则必须与服务端设置的ApplicationName相匹配;对于服务激活对象,访问时必须提供ApplicationName,此时两种方式的Uri为下面的形式:

protocal://hostadrress:port/ApplicationName/ObjectUrl       // Server Activated
protocal://hostadrress:port                                            // Client Activated Object
protocal:// hostadrress:port/ApplicationName                  // Client Activated Object

       比如,如果通道采用协议为tcp,服务器地址为127.0.0.1,端口号为8051,ApplicationName设为DemoApp,ObjectUrl设为RemoteObject(ObjUrl为使用RegisterWellKnownServiceType()方法注册服务激活对象时第2个参数所提供的字符串;注意客户激活对象不使用它),则客户端在访问时需要提供的地址为:

tcp://127.0.0.1:8051/DemoApp/RemoteObject   // Server Activated Object
tcp://127.0.0.1:8051/DemoApp                // Client Activated Object
tcp://127.0.0.1:8051                        // Client Activated Object

        如果RemotingConfiguration类型没有设置ApplicationName静态属性,则客户端在获取远程对象时不需要提供ApplicationName,此时Url变为下面形式:

protocal://hostadrress:port/ObjectUrl       // Server Activated Object
protocal://hostadrress:port                 // Client Activated Object

posted @ 2011-03-10 10:59  雁北飞  阅读(243)  评论(0编辑  收藏  举报