摘要:本文提供了 Microsoft .NET Remoting 框架的技术概述,其中包括了使用 TCP 通道或 HTTP 通道的示例。
简介
Microsoft? .NET Remoting 提供了一种答应对象通过应用程序域与另一对象进行交互的框架。这种框架提供了多种服务,包括激活和生存期支持,以及负责与远程应用程序进行消息传输的通讯通道。格式化程序用于在消息通过通道传输之前,对其进行编码和解码。应用程序可以在注重性能的场合使用二进制编码,在需要与其他远程处理框架进行交互的场合使用 xml 编码。在从一个应用程序域向另一个应用程序域传输消息时,所有的 XML 编码都使用 SOAP 协议。出于安全性方面的考虑,远程处理提供了大量挂钩,使得在消息流通过通道进行传输之前,安全接收器能够访问消息和序列化流。
远程对象注册在远程计算机的应用程序域中。远程对象被封送以生成 ObjRef。ObjRef 包含了从网络上的任意位置定位和访问远程对象所需的所有信息,包括:类的增强名称、类的层次结构(其父类)、类实现的所有接口的名称、对象 URI 和所有已注册的可用通道的具体信息。在接收到对某个远程对象的请求时,远程处理框架使用对象 URI 来检索为该对象创建的 ObjRef 实例。
客户端通过调用 new 或某个 Activator 函数(例如 CreateInstance)来激活远程对象。对于服务器激活对象,远程对象的 TransparentProxy 将在客户端应用程序域中生成并返回到客户端,这时不执行任何远程调用。只有在客户端调用远程对象的某个方法时,该远程对象才会被激活。此方案明显不适合客户端激活对象,因为客户端希望框架只在得到请求时才激活对象。当客户端调用某个激活方法时,客户端上会创建一个激活代理,并且将使用 URL 和对象 URI 作为终结点在服务器的远程激活器上初始化一个远程调用。远程激活器激活该对象,然后 ObjRef 流向客户端,并被取消封送以生成一个返回给客户端的 TransparentProxy。
注册了远程对象后,框架将为该对象创建一个对象引用,然后从程序集中提取与该对象相关的必要元数据。随后,这一信息将与 URI 和程序集名称一起存储在对象引用中(该对象引用将被写入一个用于跟踪已注册远程对象的远程处理框架表中)。请注重,除了在客户端试图调用对象上的某个方法或从客户端激活对象时以外,注册进程不会实例化远程对象自身。
现在,任何知道该对象 URI 的客户端都可以使用 ChannelServices 注册通道,并调用 new、GetObject 或 CreateInstance 激活对象,从而获得该对象的一个代理。以下代码片断显示了该操作的示例:
GetObject 或 new 可用于服务器激活对象。请注重,使用这两个调用时不会实例化对象,实际上不会生成任何网络调用。框架从元数据获得了创建代理所需的足够信息,但并未连接到远程对象上。只有在客户端调用代理上的某个方法时才会建立网络连接。当调用抵达服务器时,框架将从消息中提取 URI,检查远程处理框架表以便定位与 URI 匹配的对象引用,然后在必要时将对象实例化,并将方法调用转发至对象。假如将对象注册为 SingleCall,则完成方法调用后该对象会取消。每次调用一个方法时,都会创建一个新的实例。GetObject 和 new 之间的唯一差别在于,前者答应指定 URL 作为参数,而后者从配置中获得 URL。
CreateInstance 或 new 可用于客户端激活对象。两者都答应使用带参数的构造函数来实例化对象。客户端激活对象的生存期由远程处理框架提供的租用服务控制。对象租用的内容在下一节中说明。 更多的请看:http://www.QQread.com/windows/2003/index.Html 对象的租用生存期
public class Foo : MarshalByRefObject { public override Object InitializeLifetimeService() { ILease lease = (ILease)base.InitializeLifetimeService(); if (lease.CurrentState == LeaseState.Initial) { lease.InitialLeaseTime = TimeSpan.FromMinutes(1); lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); lease.RenewOnCallTime = TimeSpan.FromSeconds(2); } return lease; } } 只有当租用处于初始状态时,才可以更改租用属性。InitializeLifetimeService 的实现通常调用基类的相应方法,来检索远程对象的现有租用。假如在此之前从未对该对象封送过,则返回的租用会处于其初始状态且可以设置租用属性。一旦封送了对象,则租用会从初始状态变为激活状态,并忽略任何初始化租用属性的尝试(但有一种情况例外)。激活远程对象时将调用 InitializeLifetimeService。通过激活调用可以提供一个租用发起者的列表,而且当租用处于激活状态时,可以随时将其他发起者添加到列表中。
可以下列方式延长租用时间:
客户端可以调用 Lease 类上的 Renew 方法。
租用可以向某个发起者请求 Renewal。
当客户端调用对象上的某个方法时,RenewOnCall 值会自动更新租用。 一旦租用过期,其内部状态会由 Active 变为 EXPired,且不再对发起者进行任何调用,对象也会被作为垃圾回收。一般情况下,假如发起者分散在 Web 上或位于某个防火墙的后面,远程对象回叫发起者时会碰到困难。因此,发起者不必与客户端处于同一位置,只要远程对象能够访问得到,它可以为网络上的任意位置。