初試.NET Remoting
雖然使用.NET Remoting已經一陣子了,不過,最近對於它的生命週期的議題有點疑惑。所以就想說自已寫一個簡單的Remoting來測試一下。如果想看英文的.NET Remoting相關文章的話,可以參考這篇。
首先因為Remoting物件是需要在兩個不同的AppDomain中使用的,所以這個物件的定義應該是要讓Remoting Server及Remoting Client兩邊都能認得。要達到這樣的目的,一種作法就是在專案中建立一個「類別庫」。在這個類別庫中,定義一個介面。例如本範例中的IRemoteServer:
![IRemoteServer](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_sAlnkTaCMH6XpA37gV5J-EKYnDrg-1ObxbgRAeFDlUnAxJ6Hjhi1at1lFfBmcbqq8Vx77LcOOdYlrqDqu1_fzblcrFPZmuZ72MpxtGL2A99FETszgeBzQdZe4eEZp0rA=s0-d)
接著再新增一個主控台專案來實作一個RemoteServer:
![MyServer](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_vbjksSArhPUZqxpSSAmQIuWZF6tjADu4FRScE6XXHumLJZehDXIUxBY9eupL0b1JrbSyqCHowLJCruukbpgYe4UC0e7mdhRZ9XMjgxruY-drAIA21h3y8EY_Y=s0-d)
上面只是用先前定義的IRemoteServer介面實作出一個伺服器而已。這個伺服器類別除了要實作IRemoteServer外,另外還要再繼承自MarshalByRefObject。一般而言,只要繼承MarshalByRefObject類別就好了,不用再另外寫其它的程式碼。這樣的伺服器就可以使用了。
而在這裏的範例中,我另外還覆寫了MarshalByRefObject的InitializeLieftimeService()這個函式。主要的用意就是要在覆寫的函式中傳回一個null值,表示這個Marshal By Reference的物件它的「租約」是無限期的。這樣.NET中的GC就不會自動回收這個物件了。
實作完伺服器類別後,接著就是要寫一段程式碼就它能被註冊成運作中的伺服器。
![Run Remote Server](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_umv19LOwDlf2oXjn8qyiyjZP_Y_6uYrjlNVKHIq_gcXrv3Jxxj0Uphov1lh91TGAEo2s1P0So6hBuYsIUSNtIJp645PYyWdI52XXiOQI2Ky3ytKzlegdSJq7k3=s0-d)
要註冊一個Remoting的伺服器,一開始就是要先決定所要使用的通訊協定。通訊協定主要有兩種型式,一種是HTTP;另一種是TCP。在這個範例中,我是選擇使用TCP。當然你也可以選用HTTP。
建立好Channel物件後,再用ChannelServices.RegisterChannel()來註冊這個通道。
最後就是利用RemotingConfiguration.RegisterWellKnownServiceType()這個函式來註冊你要用來在上面所註冊的通道中提供服務的伺服器。需要給的參數有:
當然,最後使用了Console.ReadLine()方式讓這個程式不會立即終止。要不然,用戶端也無法連線進來了。
接著再另外新增一個專案來撰寫我們要用來使用上面所實作出來的伺服器的用戶端。程式碼如下:
![Run Client](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_uQB4PXylbQFB3eXfCNujWH3EOd4-KWk6hg2p8ADdpUd5_FLYZLLdszIwNa_Y4X4-q-GvSa7BJi2pnlopMHZv8YWWuU4RMfQuEq6qru-4D3HpwKsaFDcG7zB08=s0-d)
在用戶端中,一開始也是要先註冊一個Channel。接著再使用Activator.GetObject()函式來取得伺服器端的代理物件(Proxy)。當然記得要將取得的Object型別轉型成我們預期的IRemoteServer型別,以便使用IRemoteServer介面中所定義的函式。
就這樣,一個簡單的Remoting伺服器及用戶端就完成了。
首先因為Remoting物件是需要在兩個不同的AppDomain中使用的,所以這個物件的定義應該是要讓Remoting Server及Remoting Client兩邊都能認得。要達到這樣的目的,一種作法就是在專案中建立一個「類別庫」。在這個類別庫中,定義一個介面。例如本範例中的IRemoteServer:
接著再新增一個主控台專案來實作一個RemoteServer:
上面只是用先前定義的IRemoteServer介面實作出一個伺服器而已。這個伺服器類別除了要實作IRemoteServer外,另外還要再繼承自MarshalByRefObject。一般而言,只要繼承MarshalByRefObject類別就好了,不用再另外寫其它的程式碼。這樣的伺服器就可以使用了。
而在這裏的範例中,我另外還覆寫了MarshalByRefObject的InitializeLieftimeService()這個函式。主要的用意就是要在覆寫的函式中傳回一個null值,表示這個Marshal By Reference的物件它的「租約」是無限期的。這樣.NET中的GC就不會自動回收這個物件了。
實作完伺服器類別後,接著就是要寫一段程式碼就它能被註冊成運作中的伺服器。
要註冊一個Remoting的伺服器,一開始就是要先決定所要使用的通訊協定。通訊協定主要有兩種型式,一種是HTTP;另一種是TCP。在這個範例中,我是選擇使用TCP。當然你也可以選用HTTP。
建立好Channel物件後,再用ChannelServices.RegisterChannel()來註冊這個通道。
最後就是利用RemotingConfiguration.RegisterWellKnownServiceType()這個函式來註冊你要用來在上面所註冊的通道中提供服務的伺服器。需要給的參數有:
- 伺服器類別的型別
- 提供服務的服務名稱,也是一個識別碼
- 建立伺服器物件時的型式
- Singleton:只會產生一個伺服器物件來服務每次連線進來的要求
- SingleCoall:每次連線進來的要求都會建立一個新的伺服器物件來服務
當然,最後使用了Console.ReadLine()方式讓這個程式不會立即終止。要不然,用戶端也無法連線進來了。
接著再另外新增一個專案來撰寫我們要用來使用上面所實作出來的伺服器的用戶端。程式碼如下:
在用戶端中,一開始也是要先註冊一個Channel。接著再使用Activator.GetObject()函式來取得伺服器端的代理物件(Proxy)。當然記得要將取得的Object型別轉型成我們預期的IRemoteServer型別,以便使用IRemoteServer介面中所定義的函式。
就這樣,一個簡單的Remoting伺服器及用戶端就完成了。
留言
張貼留言