1. 程式人生 > >.Net Remoting的雙向通訊和Windows Service的宿主服務

.Net Remoting的雙向通訊和Windows Service的宿主服務

原文:.Net Remoting的雙向通訊和Windows Service的宿主服務

     作為微軟分散式技術之一的.Net Remoting,從效能、安全等各方面來說都是相對比較穩定的,也是一項比較成熟的分散式技術。

     從學習.Net Remoting至今,僅僅只使用了一次這門技術,是在去年的一個IM產品中。最近公司的產品出現了很多問題,伺服器、通訊介面、網站都陸續被攻擊(DDOS)。這對於做網際網路產業的同行來說就清楚這裡面的關係,強大的DDOS攻擊可以直接讓產品無法正常運營甚至停止運營。

     經過一系列的分析,我打算使用.Net Remoting這門技術人為的通過程式設計開發的方式來解決上述的一些問題。其中.Net Remoting的雙向通訊機制可以解決產品中的部門業務流程(比如線上充值,充值成功|失敗通知客戶端),從通訊效率上來說也優於WEB應用介面(比如Alipay的支付介面)。基於Windows Service的宿主服務、或通過IIS來宿主Remoting的服務都是比較方便的。不過我放棄了基於IIS部署.Net Remoting,IIS部署的服務始終都無法逃避開DDOS的攻擊。 Windows Service相比之下更適合於防止DDOS攻擊。

     現在有一個小的功能需求,我們要做一個聊天應用,要求使用.Net Remoting來提供遠端介面,當客戶端呼叫.Net Remoting遠端介面傳送訊息到伺服器後,伺服器對詳細進行一系列的處理(如在多人聊天的情況下廣播訊息,一對一聊天的情況下傳遞訊息到另一客戶端,其中還可能包括寫資料庫等多項操作),這裡為了方便演示我就將訊息回發給自己。

     好的,瞭解清楚了需求我們可以定義兩個介面,一個應用於傳送訊息的介面,一個應用於回發訊息的介面,從某種角度(如WCF中)也可以叫契約。

 1  namespace  ChatRoom.Contract
 2  {
 3       public   interface  IDuplexChat
 4      {
 5           void  SendMessage( string  message, IChatCallback callBack);
 6      }
 7  }
 8  namespace  ChatRoom.Contract
 9  {
10       ///   <summary>
11       ///  伺服器端回撥介面
12       ///   </summary>
13       public   interface  IChatCallback
14      {
15           ///   <summary>
16           ///  回撥方法,顯示聊天訊息
17           ///   </summary>
18           ///   <param name="message"></param>
19           void  ShowMessage( string  message);
20      }
21  }

 

     介面定義好了,現在可以提供Remoting遠端服務了,既然是.Net Remoting遠端服務,那麼就必須繼承於MarshalByRefObject,同時我們還實現IDuplexChat介面,如下:

 1  namespace  ChatRoom.Remoting
 2  {
 3       public   class  DuplexChatRemoting : MarshalByRefObject, IDuplexChat
 4      {
 5           public   void  SendMessage( string  message, IChatCallback callBack)
 6          {
 7              Console.WriteLine( " Invoke the method SendMessage() " );
 8 
 9               // do other
10              callBack.ShowMessage(message);
11          }
12      }
13  }

 

     通常開發.Net Remoting程式都會有宿主、服務和客戶端三個基本的程式模組。上面已經實現了Remoting服務,接下來就需要將該服務通過一種特定的方式來宿主(控制檯程式、IIS或Windows Service)服務,宿主服務也就是將遠端服務公佈出來,並提供一種遠端連線的方式,通常也稱其為通道(通道)。鑑於程式的靈活性我們可通過配置檔案的方式來配置.Net Remoting,比如我們通過控制檯程式來宿主服務,如下配置程式碼塊:

 1  <? xml version = " 1.0 "  encoding = " utf-8 "   ?>
 2  < configuration >
 3     < system.runtime.remoting >
 4       < application name = " ChatRoom " >
 5         < service >
 6           < wellknown mode = " SingleCall "  type = " ChatRoom.Remoting.DuplexChatRemoting,ChatRoom.Remoting "  objectUri = " ChatRoomURL " ></ wellknown >
 7         </ service >
 8         < channels >
 9           < channel  ref = " http "  port = " 8080 " >
10             < serverProviders >
11               < provider  ref = " wsdl " ></ provider >
12               < formatter  ref = " binary "  typeFilterLevel = " Full " ></ formatter >
13             </ serverProviders >
14             < clientProviders >
15               < formatter  ref = " binary " ></ formatter >
16             </ clientProviders >
17           </ channel >
18         </ channels >
19       </ application >
20     </ system.runtime.remoting >
21  </ configuration >

 

 1  namespace  ChatRoom.ConsoleHost
 2  {
 3       class  Program
 4      {
 5           static   void  Main( string [] args)
 6          {
 7              RemotingConfiguration.Configure( " ChatRoom.ConsoleHost.exe.config " false );
 8              Console.WriteLine( " .Net Remoting 服務已啟動 " );
 9              Console.Read();
10          }
11      }
12  }

 

      宿主和服務都提供好,現在我們需要一個呼叫客戶端,遠端服務已經通過宿主提供好了並定義好了通訊通道。那麼客戶端也得遵守宿主裡提供的通訊規則,既按照宿主裡提供的通訊地址和埠進行通訊。

Code

 

     客戶端的呼叫示例程式程式碼塊:

 1  namespace  ChatRoom.Client
 2  {
 3       class  Program
 4      {
 5           static  IDuplexChat proxy  =   null ;
 6           static   string  message  =   string .Empty;
 7 
 8           static   void  Main( string [] args)
 9          {
10              RemotingConfiguration.Configure( " ChatRoom.Client.exe.config " false );
11              proxy   =  (IDuplexChat)Activator.GetObject( typeof (IDuplexChat),  " http://localhost:8080/ChatRoom/ChatRoomURL " );
12 
13              message  =  Console.ReadLine();
14              SendMessage(message);
15          }
16 
17           private   static   void  SendMessage( string  message)
18          {
19              proxy.SendMessage(message,  new  ChatRoomCallBackHandler());
20 
21              message  =  Console.ReadLine();
22               if  (message  !=   " exit " )
23              {
24                  SendMessage(message);
25              }
26          }
27      }
28  }

 

     OK,如上便可完成一個雙向通訊(Client---Server|Server---Client)的簡單應用。通過上面使用控制檯的方式來宿主.Net Remoting的遠端服務,如果不小心關閉了控制檯也就管理了遠端服務,每次使用遠端服務都需要先確保服務已經成功啟動,這是非常麻煩的事情。

     我們可以通過Windows服務來避免不小心關閉遠端服務的缺點,建立Windows服務專案,直接將上面控制檯程式裡的配置檔案複製到Windows服務專案裡,在預設的Server1的程式碼檔案下裝載.Net Remoting服務就OK:

1  protected   override   void  OnStart( string [] args)
2  {
3      RemotingConfiguration.Configure( " ChatRoom.WinServiceHost.exe.config " false );
4  }

 

     光這樣是不能完成Windows服務的開安併成功安裝,還需要一個安裝程式類來對Windows服務進行一些設定。詳細請查詢Windows服務開發相關的資料。

     

     最後只需要將windows服務安裝到計算機上就OK。

 

     本文示例程式碼下載:ChatRoom.rar

 

版權說明

  本文屬原創文章,歡迎轉載,其版權歸作者和部落格園共有。  

  作      者:Beniao

 文章出處:http://beniao.cnblogs.com/  或  http://www.cnblogs.com/