天天看點

.NET簡談元件程式設計之(初識NetRemoting)

這篇文章我們來簡單的了解一下在.NET平台上有一個強有力的遠端調用武器,也是上一篇文章中我一筆帶過的遠端英雄.NetRemoting。

其實在.NET平台裡面到處都能看見Remoting的影子,隻不過我們平時都很少有機會與它接觸,因為它通常工作于“後端”,躲在界面顯示技術(如:Winform\Asp.net\Wpf.)

界面顯示層是将資訊以友好的方式展現在使用者面前,但是真正的英雄通常都在背後默默的支援它,以更華麗的效果展現。(如:Thread\WebService\Remoting\Wcf...)。

其實在我們不斷學習的過程中會慢慢的在我們腦海裡浮現出我們所學習的東西的模型,比如我們是專研.NET這門技術,那麼在我們腦子裡是否已經有了一個簡單而模糊的陰影,能看見這種陰影才證明我們剛剛入門。如果未曾有這種感覺,那麼我們對他還是一無所知,所謂知己知彼方能百戰百勝,說明我們還未入門。因為精通都是從模糊開始的,沒有人一躍而過。(這隻是本人對學習過程中的一點小小的感悟)

那麼.NetRemoting是何許人也,它是什麼?一般在哪裡才能看見它?這篇文章就是來介紹這位大人物的。[王清培版權所有,轉載請給出署名]

定義:.NetRemoting是.NET平台裡面一個專門用來處理遠端調用的架構,是已經為我們做好的、現成的架構,我們可以利用他來進行遠端調用。

.NetRemoting基本結構

那麼既然是架構它就肯定有一個結構,也就是他的工作原理。

在Remoting沒有出來之前,如果不進過一番複雜的編寫,我想誇AppDomain調用可能隻局限于統一程序内了。(這句話可能會引起誤會,我是說在.NET現有的架構基礎上而言。)

然而有了Remoting之後,一切變的簡單多了,我們隻需要了解簡單的網絡原理、套接字原理、協定等等就能很好的配置這個架構,以進行遠端調用。它将遠端調用延伸到了任何地方,不隻是在同一程序内了。

原有的同一程序内的遠端調用架構沒有變,Remoting隻是添加了點東西以支援誇程序誇網絡。(比如:RefObjet對象\RealProxy對象)

<a target="_blank" href="http://blog.51cto.com/attachment/201109/134737996.png"></a>

這是它的整體結構。用戶端的調用将被轉換成消息的傳遞,其實也就是對象的持久化過程,通過.NET序列化将對象狀态儲存在到另一端反序列化。

之前我說過Remoting是一個高擴充性的架構,從上圖中我們可以看出它的基本結構是很清晰的、很子產品化。都是通過接口關聯,隻要我們熟悉了之後就能切入自己的邏輯。[王清培版權所有,轉載請給出署名]

.NetRemoting示例

在.NET裡面不管是誇程序還是誇機器之間的AppDomain調用都是通過遠端調用技術進行處理的。在同一個程序裡面可能不會涉及到實體上的通訊,直接拿到代理就OK了,隻是一些邏輯宿主之間的處理。

那麼我們來看一個簡單的示例:

1:對照上圖,最下面的是關于通訊的端點,那麼我們首先需要設定一個能夠進行遠端通訊的位址,在Remoting裡面就是Channel(信道),消息從信道出去流線伺服器端的信道。

在Remoting裡面系統提供給了我們三種類型的信道,分别是Ipc\Tcp\Http。Ipc:是程序間調用用的,Tcp:是用TCP的協定來處理通訊,HTTP:是用HTTP協定來處理通訊。我們根據項目的需要可以進行設定。

代碼注冊信道:

IDictionary dipropertis = new Hashtable();  

dipropertis["name"] = "Myserverchannel";//信道名稱  

dipropertis["port"] = 8005;//端口  

IChannel tcpchannel = new TcpChannel(dipropertis, null, binaryformatter);//TCP信道  

ChannelServices.RegisterChannel(tcpchannel);  

IChannel httpchannel = new HttpChannel(8006);//HTTP  

ChannelServices.RegisterChannel(httpchannel);  

IChannel ipcchannel = new IpcChannel("myport");//IPC程序間通訊  

ChannelServices.RegisterChannel(ipcchannel); 

所有的通道Channel都是來自IChannel接口,是以我們可以定義自己的一些通訊實作。

上圖代碼中我分别注冊了三種類型的通道,通道也就是通訊的過程。對于IPC類型的通道我們隻需要提供一個管道名稱就行了。如果我們使用預設的Channel構造函數,隻需要提供端口就行了,但是如果要設定信道名稱就需要用字典的方式進行多屬性的設定,因為沒有提供這方面的構造函數重載。在我們注冊第一個TCP通道的時候,我定義了一個鍵值對的Hashtable,鍵name的代表信道名稱,port代表端口。

上述代碼看來,通道就是具體通訊的細節,終結點在哪裡?使用的消息是什麼?這樣就能完好的把消息送到網絡的另一端。程序間通訊IPC是通過管道的機制實作的,是以不涉及端口、網絡。

代碼注冊消息格式化器:

通道是位于Remoting整體架構的最末端,底層通訊的細節。在這上面一層是消息格式化器,也就是對象的序列化過程,在對象的持久化狀态和托管記憶體狀态之間轉換。

我們來看一下怎麼在服務端注冊消息格式化器的:

//注冊信道  

BinaryServerFormatterSinkProvider binaryformatter = new BinaryServerFormatterSinkProvider();//信道消息處理程式  

binaryformatter.TypeFilterLevel = TypeFilterLevel.Full;//完全序列化級别  

SoapServerFormatterSinkProvider soapformatter = new SoapServerFormatterSinkProvider();  

soapformatter.TypeFilterLevel = TypeFilterLevel.Full; 

 系統也我們實作了兩種類型的對象格式化方式,二進制、SOAP。

對象的TypeFilterLevel屬性是設定格式化器的級别,由于系統預設的序列化級别隻能序列化簡單的托管類型,如果要想序列化複雜而危險的對象我們需要設定該枚舉值。

 在注冊通道的時候可以将格式化器的執行個體帶進去,好讓通道知道它的消息如何被格式化。

 代碼注冊服務類型:

在往上走就到代理的子產品,代理在這篇文章中我就不扯了,對于這篇文章它不是重點。代理在我們日常開發中不太會去深入的去研究它,比較複雜,基本上被隐藏了。我們隻需要了解它就行了。有興趣的可以檢視相關資料。

我們來看一下最上層的代碼:

//注冊類型  

RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyClassLibrary.Class1), "Class1", WellKnownObjectMode.SingleCall);  

            //用戶端激活模式  

RemotingConfiguration.RegisterActivatedServiceType(typeof(MyClassLibrary.Class2)); 

伺服器端要想提供服務,就需要将提供服務的對象進行注冊。好讓伺服器知道提供了那些服務。

RemotingConfiguration對象提供了很多靜态方法,我們可以通過RegisterWellKnownServiceType方法注冊伺服器端激活模式,或者通過RegisterActivatedServiceType方法注冊用戶端激活模式。這兩種激活模式的差别在後續的文章中講會講解到。[王清培版權所有,轉載請給出署名]

用戶端代碼:

我們看一下用戶端該做些什麼:

string uri = "tcp://localhost:8005";  

  RemotingConfiguration.RegisterActivatedClientType(typeof(MyClassLibrary.Class2), uri);  

   RemotingConfiguration.RegisterWellKnownClientType(typeof(MyClassLibrary.Class1), uri + "/Class1"); 

用戶端隻需要通過RemotingConfiguration中的關于用戶端注冊的方法注冊遠端服務的類型,當我們在執行個體化對象的時候Remoting會自動的幫我們進行遠端處理。

 結:這篇文章隻是粗略講解一下Remoting的結構。下一篇文章我們将更深入一點的了解Remoting,包括激活模式、管理配置等。

 本文轉自 王清培 51CTO部落格,原文連結:http://blog.51cto.com/wangqingpei557/668343,如需轉載請自行聯系原作者

繼續閱讀