摘要:本文提供了 Microsoft .NET Remoting 框架的技術(shù)概述,其中包括了使用 TCP 通道或 HTTP 通道的示例。
簡介
Microsoft? .NET Remoting 提供了一種答應(yīng)對象通過應(yīng)用程序域與另一對象進(jìn)行交互的框架。這種框架提供了多種服務(wù),包括激活和生存期支持,以及負(fù)責(zé)與遠(yuǎn)程應(yīng)用程序進(jìn)行消息傳輸?shù)耐ㄓ嵧ǖ馈8袷交绦蛴糜谠谙⑼ㄟ^通道傳輸之前,對其進(jìn)行編碼和解碼。應(yīng)用程序可以在注重性能的場合使用二進(jìn)制編碼,在需要與其他遠(yuǎn)程處理框架進(jìn)行交互的場合使用 xml 編碼。在從一個(gè)應(yīng)用程序域向另一個(gè)應(yīng)用程序域傳輸消息時(shí),所有的 XML 編碼都使用 SOAP 協(xié)議。出于安全性方面的考慮,遠(yuǎn)程處理提供了大量掛鉤,使得在消息流通過通道進(jìn)行傳輸之前,安全接收器能夠訪問消息和序列化流。
遠(yuǎn)程對象注冊在遠(yuǎn)程計(jì)算機(jī)的應(yīng)用程序域中。遠(yuǎn)程對象被封送以生成 ObjRef。ObjRef 包含了從網(wǎng)絡(luò)上的任意位置定位和訪問遠(yuǎn)程對象所需的所有信息,包括:類的增強(qiáng)名稱、類的層次結(jié)構(gòu)(其父類)、類實(shí)現(xiàn)的所有接口的名稱、對象 URI 和所有已注冊的可用通道的具體信息。在接收到對某個(gè)遠(yuǎn)程對象的請求時(shí),遠(yuǎn)程處理框架使用對象 URI 來檢索為該對象創(chuàng)建的 ObjRef 實(shí)例。
客戶端通過調(diào)用 new 或某個(gè) Activator 函數(shù)(例如 CreateInstance)來激活遠(yuǎn)程對象。對于服務(wù)器激活對象,遠(yuǎn)程對象的 TransparentProxy 將在客戶端應(yīng)用程序域中生成并返回到客戶端,這時(shí)不執(zhí)行任何遠(yuǎn)程調(diào)用。只有在客戶端調(diào)用遠(yuǎn)程對象的某個(gè)方法時(shí),該遠(yuǎn)程對象才會(huì)被激活。此方案明顯不適合客戶端激活對象,因?yàn)榭蛻舳讼M蚣苤辉诘玫秸埱髸r(shí)才激活對象。當(dāng)客戶端調(diào)用某個(gè)激活方法時(shí),客戶端上會(huì)創(chuàng)建一個(gè)激活代理,并且將使用 URL 和對象 URI 作為終結(jié)點(diǎn)在服務(wù)器的遠(yuǎn)程激活器上初始化一個(gè)遠(yuǎn)程調(diào)用。遠(yuǎn)程激活器激活該對象,然后 ObjRef 流向客戶端,并被取消封送以生成一個(gè)返回給客戶端的 TransparentProxy。
注冊了遠(yuǎn)程對象后,框架將為該對象創(chuàng)建一個(gè)對象引用,然后從程序集中提取與該對象相關(guān)的必要元數(shù)據(jù)。隨后,這一信息將與 URI 和程序集名稱一起存儲(chǔ)在對象引用中(該對象引用將被寫入一個(gè)用于跟蹤已注冊遠(yuǎn)程對象的遠(yuǎn)程處理框架表中)。請注重,除了在客戶端試圖調(diào)用對象上的某個(gè)方法或從客戶端激活對象時(shí)以外,注冊進(jìn)程不會(huì)實(shí)例化遠(yuǎn)程對象自身。
現(xiàn)在,任何知道該對象 URI 的客戶端都可以使用 ChannelServices 注冊通道,并調(diào)用 new、GetObject 或 CreateInstance 激活對象,從而獲得該對象的一個(gè)代理。以下代碼片斷顯示了該操作的示例:
GetObject 或 new 可用于服務(wù)器激活對象。請注重,使用這兩個(gè)調(diào)用時(shí)不會(huì)實(shí)例化對象,實(shí)際上不會(huì)生成任何網(wǎng)絡(luò)調(diào)用。框架從元數(shù)據(jù)獲得了創(chuàng)建代理所需的足夠信息,但并未連接到遠(yuǎn)程對象上。只有在客戶端調(diào)用代理上的某個(gè)方法時(shí)才會(huì)建立網(wǎng)絡(luò)連接。當(dāng)調(diào)用抵達(dá)服務(wù)器時(shí),框架將從消息中提取 URI,檢查遠(yuǎn)程處理框架表以便定位與 URI 匹配的對象引用,然后在必要時(shí)將對象實(shí)例化,并將方法調(diào)用轉(zhuǎn)發(fā)至對象。假如將對象注冊為 SingleCall,則完成方法調(diào)用后該對象會(huì)取消。每次調(diào)用一個(gè)方法時(shí),都會(huì)創(chuàng)建一個(gè)新的實(shí)例。GetObject 和 new 之間的唯一差別在于,前者答應(yīng)指定 URL 作為參數(shù),而后者從配置中獲得 URL。
CreateInstance 或 new 可用于客戶端激活對象。兩者都答應(yīng)使用帶參數(shù)的構(gòu)造函數(shù)來實(shí)例化對象。客戶端激活對象的生存期由遠(yuǎn)程處理框架提供的租用服務(wù)控制。對象租用的內(nèi)容在下一節(jié)中說明。 更多的請看: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; } } 只有當(dāng)租用處于初始狀態(tài)時(shí),才可以更改租用屬性。InitializeLifetimeService 的實(shí)現(xiàn)通常調(diào)用基類的相應(yīng)方法,來檢索遠(yuǎn)程對象的現(xiàn)有租用。假如在此之前從未對該對象封送過,則返回的租用會(huì)處于其初始狀態(tài)且可以設(shè)置租用屬性。一旦封送了對象,則租用會(huì)從初始狀態(tài)變?yōu)榧せ顮顟B(tài),并忽略任何初始化租用屬性的嘗試(但有一種情況例外)。激活遠(yuǎn)程對象時(shí)將調(diào)用 InitializeLifetimeService。通過激活調(diào)用可以提供一個(gè)租用發(fā)起者的列表,而且當(dāng)租用處于激活狀態(tài)時(shí),可以隨時(shí)將其他發(fā)起者添加到列表中。
可以下列方式延長租用時(shí)間:
客戶端可以調(diào)用 Lease 類上的 Renew 方法。
租用可以向某個(gè)發(fā)起者請求 Renewal。
當(dāng)客戶端調(diào)用對象上的某個(gè)方法時(shí),RenewOnCall 值會(huì)自動(dòng)更新租用。 一旦租用過期,其內(nèi)部狀態(tài)會(huì)由 Active 變?yōu)?EXPired,且不再對發(fā)起者進(jìn)行任何調(diào)用,對象也會(huì)被作為垃圾回收。一般情況下,假如發(fā)起者分散在 Web 上或位于某個(gè)防火墻的后面,遠(yuǎn)程對象回叫發(fā)起者時(shí)會(huì)碰到困難。因此,發(fā)起者不必與客戶端處于同一位置,只要遠(yuǎn)程對象能夠訪問得到,它可以為網(wǎng)絡(luò)上的任意位置。