远程处理的工作原理
.NET 远程处理框架为开发人员提供先进的分布式对象模型,该模型允许在网络中的不同公共语言运行库之间或者在同一公共语言运行库中的不同 AppDomain 之间进行远程方法调用。与远程对象的所有交互都通过代理发生,而且客户端无法直接访问远程对象,因为该对象仅在其自己的 AppDomain 内才有意义。下列规则适用:所有远程对象都必须从 MarshalByRefObject 派生。与远程对象的任何交互都通过代理使用引用发生。客户端必须获取此激活远程对象的代理。此操作可通过调用 CreateInstance、GetObject 或 new 来完成。当进行远程调用时,本地对象可用作参数。因为对远程对象来说,对本地对象的引用没有意义,所以当本地对象用作远程调用中的参数或者作为远程调用的结果返回时,所有本地对象都通过值传递。由值传递的所有对象都必须可序列化。这一点可通过实现 ISerializable 接口或使用 [serializable] 自定义属性标记该对象来完成。必须先激活远程对象,客户端才能使用它们。框架支持两种激活模型:服务器激活和客户端激活。服务器激活意味着当客户端试图访问对象时,该对象自动在服务器上创建。客户端激活意味着对象将作为来自客户端的蓄意激活请求的结果而创建。有两种激活模型的原因是因为在分布式对象模型中,对象的生存期经常成为要考虑的问题。在某些情况下,要求远程对象在调用之间维护状态。在其他情况下,要求无状态对象,这样在每次调用时都可以为每个调用方提供一个新的对象实例。有时客户端要求对对象的生存期有更多的控制(相比服务器激活所提供的控制而言)。通过同时允许服务器激活和客户端激活,开发人员可为手头的任务自由选取最佳的激活模型。
服务器对象在尚未创建时如何能侦听客户端呢?在网络上的某个位置创建并部署服务器对象,该对象在此处侦听要连接的客户端。当客户端出现时,有关该调用和参数的详细信息被传输给该服务器对象,然后方法执行,并将可选结果传输回该客户端。部署服务器对象的步骤如下所示:
所有远程对象都必须注册到公共语言运行库,这样客户端才能访问它们。需要向公共语言运行库提供关于对象的特定详细信息,如应加载以激活该对象的程序集的名称、该对象的命名空间和类型名以及可在其中访问该对象的终结点的名称。框架确保一个对象不会在同一 AppDomain 中注册多次。还需要注册客户端将用来与该对象进行通讯的所有信道。每个信道使用特定协议,如 TCP、HTTP 或 SMTP。在合适的地方,可注册多个信道。该对象的详细信息存储在一个由框架管理的表中。该表还存储了随后为对象创建的对象引用。对象引用将用于表示不同 AppDomain 中的注册对象,并将在需要时被序列化并传输到客户端。然后,注册的信道开始侦听是否有客户端要连接。部署远程对象后,客户端可以连接和调用服务器对象上的方法。客户端注册将用来与该远程对象进行通讯的信道。此处唯一的要求是服务器应在类似信道上正在侦听。随后,客户端通过调用 new、GetObject 或 CreateInstance 激活该对象。随激活请求提供有关于该远程对象的类型和位置的充分信息,以便框架创建表示该远程对象的代理。此过程是本地的,明白这一点很重要,并且根本没有对该远程对象进行调用。代理也存储在本地的一个表中,客户端的任何其他激活请求都接收该代理。在服务器激活对象的情况下,客户端使用它在激活时接收的代理调用该远程对象上的方法。如果客户端信道尚未连接到远程信道,则客户端信道尝试建立此连接。建立连接后,消息接收使用指定协议连接到处理通讯详细信息的连接的任一端。方法调用的详细信息加载到 Message 对象中,该对象被序列化并传输到服务器。序列化的类型取决于信道。例如,使用 HTTP 信道时,所有消息序列化为 XML 并通过 SOAP 传输。另一方面,TCP 使用二进制序列化。消息到达服务器端后,框架重新汇编原始调用、激活目标对象(如果它尚未激活)并将调用转发给相关对象。结果返回客户端时路径与消息发出的路径正好相反,它被打包到传输回该客户端的消息中。如果目标对象是 SingleCall 类型,则在调用完成后自动对其进行垃圾回收。

解决方案 »

  1.   

    远程处理概述
    公共语言运行库远程处理结构提供一组丰富的类,这些类使开发人员可以不必考虑大部分部署和管理远程对象的复杂工作。即使要处理在不同运行库环境中运行的应用程序,对远程对象调用方法也几乎与调用本地方法相同。本“快速入门”目的在于提供有关“远程处理”的简短介绍,并描述所涉及的原则,以便您可以根据需要生成更复杂的应用程序。对远程对象、HTTP、TCP 和 URL 有基本的了解可帮助理解这些示例。 “远程处理”是内置到公共语言运行库中的框架,它可用于生成复杂的分布式应用程序和网络服务。虽然它与其他平台上的类似 .NET 框架具有许多相同的功能,但它还提供一组特有的功能,这是任何其他框架所没有的:
    代理对象。当客户端创建远程对象的实例时,它接收服务器上该类实例的代理。对代理调用的所有方法都将自动转发到该远程类,并且任何结果都将返回到客户端。从客户端的角度来看,此过程与进行本地调用没有任何区别。远程对象引发的任何异常都将被自动返回到客户端。这使客户端得以在代码节周围使用正常的 Try 块和 catch 块捕获和处理异常。
    对象传递。所有远程创建的对象都由引用返回而且必须从 MarshallByRefObject 派生。作为参数传递给远程方法调用的对象可以由值或引用转发。默认行为是由值传递,前提是使用自定义属性 [serializable] 标记了相关对象。另外,该对象可以实现 ISerializable 接口,这在应如何序列化和反序列化对象方面提供灵活性。不是用引用或值封送的对象不能进行远程处理。
    激活模型。可通过调用 new 轻松地从客户端创建远程对象。框架包含足够的“智能”,能够知道您正在处理远程对象,而且将确保该对象的实例在相关的远程应用程序中创建。创建远程对象的实例不局限于默认构造函数;您甚至可以使用需要一个或多个参数的构造函数执行此操作。Activator 类包含 CreateInstance 和 GetObject 两个方法,它们也可用于创建远程对象的实例。前者可用于替代 new 来创建对象实例,而后者通常用于连接到位于指定 URL 的对象。
    无状态和有状态对象。框架规定将远程对象创建为无状态。如果将某个对象配置为 SingleCall,则当对该对象调用方法时会创建该对象。该对象处理调用,返回可选结果,然后被垃圾回收器回收。这样,对于每个调用客户端都始终连接到新对象。将对象配置为 Singleton 将确保无论何时调用该对象,所有客户端都连接到同一对象。ClientActivated 对象允许客户端在远程对象创建后将参数传递给该对象的构造函数。在客户端上对客户端激活的对象的每个激活请求(Activator.CreateInstance 或者 new 与配置文件中的项相结合)都导致在服务器上创建一个新对象。
    信道和序列化。当客户端对远程对象调用方法时,远程处理框架自动序列化与该请求关联的任何数据,然后使用信道将数据传输到远程对象。一些支持的比较常用的信道包括 HTTP、TCP 和 SMTP。对于 HTTP 而言,框架使用 SOAP 协议以 XML 格式在客户端和服务器之间来回传输数据。HTTP 的默认序列化格式化程序为 SOAP 格式化程序。因为程序员可以创建用于任何信道的自定义格式化程序,所以远程处理框架可以配置为与其他平台上的任何外部 .NET 框架协同工作。TCP 信道默认情况下使用普通套接字和“二进制序列化”,而且可用于与远程服务器上的任何对象进行通讯。
    基于租约的生存期。远程对象的生存期由租约机制控制。当第一次创建对象时,赋予它一个租约时间。当对象的租约时间降到零时,该对象将与远程处理结构断开连接,而且当 AppDomain 内对该对象的所有引用都释放后,该对象将由垃圾回收器回收。框架提供许多机制,允许客户端延长该对象的租约,从而维持其生命。
    在 IIS 中承载对象。远程对象可以轻松地寄宿在 IIS 中。这样使任何客户端都能使用常规 HTTP 通过端口 80 连接到该对象。还可以使用 Internet Explorer 创建允许用户连接到远程对象的 Web 页。