Remoting 基礎的補充

2021-07-11 23:46:46 字數 3614 閱讀 3760

在remoting中,允許同時建立多個通道,即根據不同的埠建立不同的通道。但remoting要求通道的名字必須不同,因為它要用來作為通道的唯一識別符號。雖然ichannel有channelname屬性,但這個屬性是唯讀的。因此乙個標準的建立remoting 程式的方法無法實現同時註冊多個通道的要求。

這個時候,我們必段要用到system.collection中的idictionary介面。

註冊tcp通道:

idictionary tcpprop = new hashtable();

tcpprop["name"] = "tcp9090";

tcpprop["port"] = 9090;

ichannel channel = new tcpchannel(tcpprop,new binaryclientformattersinkprovider(),new binaryserverformattersinkprovider());

channelservices.registerchannel(channel);

註冊http通道:

在name屬性中,定義不同的通道名稱就可以了。

由於伺服器和客戶端都要用到遠端物件,通常的方式是生成兩份完全相同的物件dll,分別新增引用。不過為了**的完全性,且降低客戶端對遠端物件元資料的相關性,我們有必要對這種方式進行改動。即在伺服器端實現遠端物件,而在客戶端則刪除這些實現的元資料。

由於啟用模式的不同,在客戶端建立物件的方法也不同,所以要分離元資料的相關性,也應分為兩種情況。

wellknown啟用模式:

通過介面來實現,在伺服器端,提供介面和具體類的實現,而在客戶端僅提供介面:

public inte***ce iserverobject

public class serverobject:marshalbyrefobject,iserverobject

注意:兩邊生成該物件程式集的名字必須相同,嚴格地說,是命名空間的名字必須相同。

客戶端啟用模式:

如前所述,對於客戶端啟用模式,不管是使用靜態方法,還是使用createinstance()方法,都必須在客戶端呼叫建構函式例項化物件。所以,在客戶端我們提供程物件,就不能只提供介面,而沒有類的實現。實際上,要做到與遠端物件元資料的分離,可以由兩種方法供選擇:

a、利用wellknown啟用模式模擬客戶端啟用模式:

方法是利用設計模式中的「抽象工廠」,下面的類圖表描述了總體解決方案:

我們在伺服器端的遠端物件中加上抽象工廠的介面和實現類:

public inte***ce iserverobject

public inte***ce iserverobjfactory

public class serverobject:marshalbyrefobject,iserverobject

}public class serverobjfactory:marshalbyrefobject,iserverobjfactory

}

然後再客戶端的遠端物件中只提供工廠介面和原來的物件介面:

public inte***ce iserverobject

public inte***ce iserverobjfactory

我們用wellknown啟用模式註冊遠端物件,在伺服器端:

//傳遞物件:

remotingconfiguration.registerwellknownservicetype(typeof(serverremoteobject.serverobjfactory),"servicemessage",wellknownobjectmode.singlecall);

注意這裡註冊的不是serverobject類物件,而是serverobjfactory類物件。

客戶端:

serverremoteobject.iserverobjfactory serve***ctory = (serverremoteobject.iserverobjfactory

)activator.getobject(typeof(

serverremoteobject.iserverobjfactory

),"tcp://localhost:8080/servicemessage");

serverremoteobject.iserverobject serverobj = serve***ctory.createinstance();

為什麼說這是一種客戶端啟用模式的模擬呢?從啟用的方法來看,我們是使用了singlecall模式來啟用物件,但此時啟用的並非我們要傳遞的遠端物件,而是工廠物件。如果客戶端要建立遠端物件,還應該通過工廠物件的createinstance()方法來獲得。而這個方法正是客戶端呼叫的。因此它的實現方式就等同於客戶端啟用模式。

b、利用替代類來取代遠端物件的元資料

實際上,我們可以用乙個trick,來欺騙remoting。這裡所說的替代類就是這個trick了。既然是提供服務,remoting傳遞的遠端物件其實現的細節當然是放在伺服器端。而要在客戶端放物件的副本,不過是因為客戶端必須呼叫建構函式,而採取的無奈之取。既然具體的實現是在伺服器端,又為了能在客戶端例項化,那麼在客戶端就實現這些好了。至於實現的細節,就不用管了。

如果遠端物件有方法,伺服器端則提供方法實現,而客戶端就提供了這個方法就ok了,至於裡面的實現,你可以是丟擲乙個異常,或者return乙個null值;如果方法返回void,那麼裡機可以是空。關鍵是這個客戶端類物件要有這個方法。這個方法的實現,其實和方法宣告差不多,所以我說是乙個trick。方法如果,建構函式也如此。

還是用**來說明這種「陰謀」,更直觀:

伺服器端

public class serverobject:marshalbyrefobject

public person getpersoninfo(string name,string ***,int age)

}

客戶端

public class serverobject:marshalbyrefobject

public person getpersoninfo(string name,string ***,int age)

}

比較客戶端和伺服器端,客戶端的方法getpersoninfo(),沒有具體的實現細節,只是丟擲乙個異常。或者直接寫上語句return null,照樣ok。我們稱客戶端的這個類為遠端物件的替代類。

python基礎補充

import random print random.choice range 10 和from random import choice print choice range 10 第一種方法 將模組的名字設定為乙個隱含在名字空間裡的全域性變數,這樣就好像訪問全域性屬性那樣訪問choice函式 第...

python基礎補充

import random print random.choice range 10 和from random import choice print choice range 10 第一種方法 將模組的名字設定為乙個隱含在名字空間裡的全域性變數,這樣就好像訪問全域性屬性那樣訪問choice函式 第...

PHP基礎補充

1.1 區域性變數 function f1 f1 echo a 無法在函式外部獲取函式內部的值,所以這個 a是未定義 1.2全域性變數 全域性變數在函式內部預設無法訪問 a 10 function f1 f1 如果想要在函式內部獲取到函式外部的值,可以給 a設定global全域性變數 b 10 fu...