|
創建以Microsoft .NET Remoting爲基礎的分佈式應用架構
摘要
本文以一個簡單的C#控制檯程序爲示例詳細闡述瞭如何採用.NET Remoting技術來構建一個典型的分佈式多點廣播應用程序架構。需要讀者具備一些.NET Remoting技術的基本概念,如果對此不太瞭解請先參考:Microsoft .NET Remoting技術概述 。
目錄
引言
在論壇裏經常看見有人問:使用.NET Remoting如何從服務器主動發出事件通知客戶端?的確,初接觸.NET Remoting的人多半會有這樣的疑問,因爲大部分的文章和書籍在介紹.NET Remoting時都只介紹了通道,對象,激活和生存週期等等概念,在談到如何進行遠程通信的時候,都只告訴讀者如何從客戶端激活一個服務器對象然後傳遞參數調用其方法。所以很多讀者都不太清楚如何從服務器向客戶端廣播信息,甚至有很多人認爲跟WEB服務器不能主動發送信息到瀏覽器一樣,.NET Remoting同樣也不能這麼做,只能採用"客戶端發出請求->服務器回覆響應"這種簡單的通訊模式,以至於在需要服務器對客戶端廣播信息時設計出兩端都放上Server和Client對象的複雜架構,既麻煩又容易出錯。
其實.NET Remoting遠程處理完全支持事件驅動的編程和使用同步和異步委託的回調函數。在.NET Remoting中你可以方便的採用事件註冊遠程回調函數,並方便的利用這種機制將服務器端信息廣播到客戶端。下面將向讀者詳細介紹這種分佈式多點廣播應用程序架構的編寫方法。
網絡物理結構圖
上面便是網絡結構示意圖,之所以說它是一個典型的分佈式應用架構是因爲基於這種網絡結構十分常見,在證券交易,期貨行情,視頻會議,遠程教學等許多方面都能派上用場。
架構設計
爲了形象化抽象的概念,我們先來了解一下電視廣播的工作流程,再結合我們的程序理解架構設計的主要思想。
電視廣播的流程是由以下四個主要機構參與其中:
1. 節目製作部門。負責製作電視節目。
2. 轉播間。負責安排節目製作部門提供的節目的廣播方式。
3. 電視塔。負責將電視信號轉化爲無線電波發送出去。
4. 電視機。負責接受無線電信號並轉換成可視的圖象。
在我們的程序中也是由四個主要的對象組成,它們的名稱和用途分別是:
1. Announcer:信息發送對象。負責發送原始信息,相當於電視節目製作部門。
2. InfoCenter: 信息中心。負責管理信息廣播機制。相當於轉播間。
3. Server:服務器。管理傳送通道,負責發送廣播數據流。相當於電視塔。
4. Receiver:接受器。接受廣播數據流,轉換成我們可以理解的信息格式。相當於電視機。
對象結構如下圖所示: 程序設計
首先我們來看一下信息中心InfoCenter對象的編寫方法(InfoCenter.cs):
using System; using System.Runtime.Remoting; namespace Distribution_Framework { //定義廣播事件的參數類 [Serializable] public class BroadcastEventArgs : EventArgs { private string msg = null; public BroadcastEventArgs(string message) { msg = message; } public string Message { get { return msg; } } } public delegate void BroadcastEventHandler(object sender, BroadcastEventArgs submitArgs); public class InfoCenter : MarshalByRefObject { public InfoCenter() { Console.WriteLine("InfoCenter created."); } public override object InitializeLifetimeService() { return null; } public event BroadcastEventHandler Broadcaster; public void Broadcasting(string message) { BroadcastEventArgs e = new BroadcastEventArgs(message); if (Broadcaster != null) { Broadcaster(this, e);//發出事件 Console.WriteLine("Broadcast:" + e.Message); } } } } 要點說明:
public delegate void BroadcastEventHandler(object sender, BroadcastEventArgs submitArgs); 定義了一個事件處理委託及其參數格式。
public event BroadcastEventHandler Broadcaster; 請注意,這一句定義了一個公共事件,需要接受廣播信息的遠程對象可以通過這個事件向InfoCenter註冊使用BroadcastEventHandler委託的遠程回調函數。這個機制有點類似有線受費電視,你如果需要收看電視臺提供的電視節目請先來登記。
接下來看看Server對象的實現(Server.cs):
using System; using System.Runtime.Remoting; namespace Distribution_Framework { class Server { public static void Main(string[] Args) { RemotingConfiguration.Configure("Server.exe.config"); Console.WriteLine("Server is running, Press Enter key to exit."); Console.ReadLine(); } } } 呵呵,是不是跟電視塔一樣簡單?基本上除了"天線"就沒別的了。 :)
下面是它的配置文件(Server.exe.config):
<configuration> <system.runtime.remoting> <application> <service> <wellknown mode="Singleton" type="Distribution_Framework.InfoCenter, InfoCenter" objectUri="Broadcast" /> </service> <channels> <channel ref="http" port="8080" /> </channels> </application> </system.runtime.remoting> </configuration> 電視廣播站已經架設好了,我們再來看看"電視機"是怎麼做的(Receiver.cs):
using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Http; namespace Distribution_Framework { class Receiver : MarshalByRefObject { InfoCenter infoCenter; public Receiver() { } public override object InitializeLifetimeService() { return null; } public void Run() { RemotingConfiguration.Configure("Receiver.exe.config"); infoCenter = new InfoCenter(); //訂閱信息 infoCenter.Broadcaster += new BroadcastEventHandler(this.BroadcastReceiver); Console.WriteLine("Ready to Recieve Message..."); Console.ReadLine(); //取消訂閱 infoCenter.Broadcaster -= new BroadcastEventHandler(this.BroadcastReceiver); } public void BroadcastReceiver(object sender, BroadcastEventArgs args) { Console.WriteLine("Received:" + args.Message);//打印接收信息 } public static void Main() { Receiver receiver = new Receiver(); receiver.Run(); } } } 要點說明:
infoCenter.Broadcaster += new BroadcastEventHandler(this.BroadcastReceiver); 還記得我們在InfoCenter中定義的那個Broadcaster事件嗎?這裏就是如何向它註冊一個遠程回調函數,相當於登記收看電視節目了。不想看了的話記得要向它取消登記哦,infoCenter.Broadcaster -= new BroadcastEventHandler(this.BroadcastReceiver);不然多收了你的錢可別耍賴。 :)
public void BroadcastReceiver(object sender, BroadcastEventArgs args) { Console.WriteLine("Received:" + args.Message); } 這個就是被服務器端遠程回調的函數。
另外要注意的是,這個客戶對象也必須要從MarshalByRefObject繼承,原因很簡單,因爲它相對於服務器來說也是一個需要進行序列化調用的遠程對象。
下面是它的配置文件(Receiver.exe.config):
<configuration> <system.runtime.remoting> <application> <client> <wellknown type="Distribution_Framework.InfoCenter, InfoCenter" url="http://localhost:8080/Broadcast" /> </client> <channels> <channel ref="http" port="0" /> </channels> </application> </system.runtime.remoting> </configuration> 請注意,port="0"表示由計算機自動選取一個最合適的端口。
我們現在電視機也有了,就差有人來送節目播放了,下面就是"電視節目製作部"的代碼(Announcer.cs):
using System; using System.Timers; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Http; namespace Distribution_Framework { class Announcer { InfoCenter infoCenter; public static void Main(string[] Args) { Announcer announcer = new Announcer(); announcer.Run(); Console.WriteLine("The announcer has been started."); Console.ReadLine(); } public void Run() { RemotingConfiguration.Configure("Announcer.exe.config"); infoCenter = new InfoCenter(); Timer timer = new Timer(1000); timer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer_Elapsed); timer.Enabled = true; } private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { string msg = "The Time is: " + DateTime.Now.ToString(); Console.WriteLine("Send Message:" + msg); infoCenter.Broadcasting(msg); } } } 在這裏,我們定義了一個定時器,每隔一秒種便向服務器發送一個計算機本地時間字符串信息,我們終於有可以收到的節目了,雖然是簡單了點。另外,請注意,就象我們可以接收很多電視頻道一樣,發送者並沒有規定只能有一個,事實上我們的確可以添加許多發送者,不過要注意線程之間的同步問題。
下面是它的配置文件(Announcer.exe.config):
<configuration> <system.runtime.remoting> <application> <client> <wellknown type="Distribution_Framework.InfoCenter, InfoCenter" url="http://localhost:8080/Broadcast" /> </client> <channels> <channel ref="http" port="0" /> </channels> </application> </system.runtime.remoting> </configuration> 眼明的讀者一下就看出來了,這個跟Receiver的配置文件一模一樣,其實它們本來就都是客戶端,配置文件當然是一樣的。
最後,我們用下列命令將它們編譯成可執行文件:
csc /t:library infocenter.cs csc /r:infocenter.dll server.cs csc /r:infocenter.dll receiver.cs csc /r:infocenter.dll announcer.cs 請先運行Server.exe然後再運行Announcer.exe,最後你可以多打開幾個Receiver,觀察它們的工作情況。注意,如果你需要在不同的計算機上向別人演示這個程序的話,請將配置文件中的localhost改成相應的計算機名稱或者是IP地址,而無須重新編譯。
總結
使用.NET編程總是這麼簡單和有趣,在上例中,你幾乎看不到什麼關於"遠程"的特殊代碼,它非常接近於普通的程序調用,事實上,如果沒有進行對 RemotingConfiguration.Configure() 的調用,你根本就不需要進行任何修改即可在單個應用程序域中編譯和運行整個應用程序。
本文着重的是定義一個基於.NET Remoting的分佈式遠程應用架構的設計模式,其一部分設計思想來自於《設計模式》中的Observer模式,如果你對使用事件和委託來實現Observer模式的概念有些模糊的話,請參考拙文:利用C#的Delegate來改進Observer模式。
參考文獻
MSDN-.NET框架開發者指南:.NET遠程處理
作者
盧彥
2002年11月1日
版權聲明 凡在本網站發表的文章,作者必須保證是原創文章;如果不是原創文章,由此帶來的版權糾紛由作者自己承擔。微軟有義務對本站點發表的文章進行審覈,但您需要考慮這些文章的使用風險。本站點僅提供一個用戶相互交換技術信息和學習的園地,並不對來自社區用戶的技術文章承擔任何風險。 |
創建以Microsoft .NET Remoting爲基礎的分佈式應用架構
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.