.NET Remoting學習筆記(二)激活方式


目錄

 

參考:百度百科  ♂風車車.Net

 

激活方式概念

在訪問遠程類型的一個對象實例之前,必須通過一個名為Activation的進程創建它並進行初始化。這種客戶端通過通道來創建遠程對象,稱為對象的激活。

激活分為兩大類:服務器端激活  客戶端激活

 

服務器端激活

又稱WellKnow(知名對象)

服務器應用程序在激活對象實例之前會在一個眾所周知的統一資源標識符(URI)上來發布這個類型。然后該服務器進程會為此類型配置一個WellKnown對象,並根據指定的端口或地址來發布對象。

服務器端激活分為:SingleTon模式  SingleCall模式

 

SingleTon模式

設置為SingleTon激活方式,則Remoting將為所有客戶端建立同一個對象實例。當對象處於活動狀態時, SingleTon實例會處理所有后來的客戶端訪問請求,而不管它們是同一個客戶端,還是其他客戶端。SingleTon實例將在方法調用中一直維持其狀態。舉例來說,如果一個遠程對象有一個累加方法(i=0;++i),被多個客戶端(例如兩個)調用。如果設置為SingleTon方式,則第一個客戶獲得值為1,第二個客戶獲得值為2,因為他們獲得的對象實例是相同的。如果熟悉Asp .Net的狀態管理,我們可以認為它是一種Application狀態。

下面貼代碼:

1.創建遠程調用處理的類

using System; using System.Runtime.Remoting.Metadata; /*code 釋迦苦僧*/
namespace MessageMarshal { /*創建發送消息委托*/
    public delegate void SendMessageHandler(string messge); [Serializable] public class TestMessageMarshal : MarshalByRefObject { private Guid ID { get; set; } /*新建對象實例時重新創建標識編號*/
        public TestMessageMarshal() { ID = Guid.NewGuid(); } /*創建發送消息事件*/
        public static event SendMessageHandler SendMessageEvent; /*發送消息*/ [SoapMethod(XmlNamespace = "MessageMarshal", SoapAction = "MessageMarshal#SendMessage")] public void SendMessage(string messge) { if (SendMessageEvent != null) SendMessageEvent(ID.ToString() + "\t" + messge); } } }
View Code

2.創建服務端代碼

using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Http; using MessageMarshal; namespace TestRemotingServer { /*code:釋迦苦僧*/ 
    class Program { static void Main(string[] args) { /*創建HTTP通道*/ HttpChannel channel = new HttpChannel(8226); /*注冊通道服務端*/ ChannelServices.RegisterChannel(channel,false); /*設置模式為 Singleton */ RemotingConfiguration.RegisterWellKnownServiceType(typeof(TestMessageMarshal),"test", WellKnownObjectMode.Singleton); Console.WriteLine("started ..."); /*接收客戶端事件*/ TestMessageMarshal.SendMessageEvent+=new SendMessageHandler(TestMessageMarshal_SendMessageEvent); Console.Read(); } static void TestMessageMarshal_SendMessageEvent(string messge) { Console.WriteLine(messge); } } }
View Code

3.創建客戶端代碼

using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Http; using System.Threading; /*code 釋迦苦僧*/
namespace TestRemotingClient { class Program { static void Main(string[] args) { HttpChannel channel = new HttpChannel(); ChannelServices.RegisterChannel(channel, false); /*注冊通道 的 遠程處理類型*/ RemotingConfiguration.RegisterWellKnownClientType(typeof(MessageMarshal.TestMessageMarshal), "http://localhost:8226/test"); /*創建消息實體*/ MessageMarshal.TestMessageMarshal TestMessage = new MessageMarshal.TestMessageMarshal(); while (true) { TestMessage.SendMessage("DateTime.Now:" + System.DateTime.Now.ToString()); Console.WriteLine("send message..."); Thread.Sleep(2000); } } } }
View Code

4.運行服務端后,開啟兩個客戶端程序,查看結果如下:

代碼示意中,當TestMessageMarshal有新實例時,其構造函數會創建不同的標識(GUID),服務端接收到客戶端的數據請求,並將標識編號輸出到界面,從界面中可以看出,多個客戶端請求的通道,服務端都是用一個通道(一個實例)來進行處理的。

 

SingleCall模式

SingleCall是一種無狀態模式。一旦設置為SingleCall模式,則當客戶端調用遠程對象的方法時, Remoting會為每一個客戶端建立一個遠程對象實例,至於對象實例的銷毀則是由GC自動管理的。同上一個例子而言,則訪問遠程對象的兩個客戶獲得的都是1。我們仍然可以借鑒Asp .Net的狀態管理,認為它是一種Session狀態。

我們修改服務端代碼如下,客戶端不需要修改:

            /*設置模式為 SingleCall */ RemotingConfiguration.RegisterWellKnownServiceType(typeof(TestMessageMarshal),"test", WellKnownObjectMode.SingleCall);   

開啟服務端,然后開啟一個客戶端,如下

從輸出結果中可以看出,每次服務端都會為每一個客戶端請求建立一個遠程對象實例。

 

客戶端激活

與WellKnown模式不同, Remoting在激活每個對象實例的時候,會給每個客戶端激活的類型指派一個URI。客戶端激活模式一旦獲得客戶端的請求,將為每一個客戶端都建立一個實例引用。SingleCall模式和客戶端激活模式是有區別的:首先,對象實例創建的時間不一樣。客戶端激活方式是客戶一旦發出調用的請求,就實例化;而SingleCall則是要等到調用對象方法時再創建。其次,SingleCall模式激活的對象是無狀態的,對象生命期的管理是由GC管理的,而客戶端激活的對象則有狀態,其生命周期可自定義。其三,兩種激活模式在服務器端和客戶端實現的方法不一樣。尤其是在客戶端,SingleCall模式是由 GetObject()來激活,它調用對象默認的構造函數。而客戶端激活模式,則通過CreateInstance()來激活,它可以傳遞參數,所以可以調用自定義的構造函數來創建實例。

1.修改服務端代碼

using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Http; using System.Runtime.Remoting.Channels.Tcp; using MessageMarshal; namespace TestRemotingServer { /*code:釋迦苦僧*/ 
    class Program { static void Main(string[] args) { /*創建HTTP通道*/ HttpChannel channel = new HttpChannel(8226); /*注冊通道服務端*/ ChannelServices.RegisterChannel(channel,false); RemotingConfiguration.ApplicationName = "test"; RemotingConfiguration.RegisterActivatedServiceType(typeof(TestMessageMarshal)); Console.WriteLine("started ..."); /*接收客戶端事件*/ TestMessageMarshal.SendMessageEvent+=new SendMessageHandler(TestMessageMarshal_SendMessageEvent); Console.Read(); } static void TestMessageMarshal_SendMessageEvent(string messge) { Console.WriteLine(messge); } } }
View Code

2.修改客戶端代碼

using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Http; using System.Threading; /*code 釋迦苦僧*/
namespace TestRemotingClient { class Program { static void Main(string[] args) { HttpChannel channel = new HttpChannel(); ChannelServices.RegisterChannel(channel, false); /*注冊通道 的 遠程處理類型*/ RemotingConfiguration.RegisterActivatedClientType(typeof(MessageMarshal.TestMessageMarshal), "http://localhost:8226/test"); /*創建消息實體*/ MessageMarshal.TestMessageMarshal TestMessage = new MessageMarshal.TestMessageMarshal(); while (true) { TestMessage.SendMessage("DateTime.Now:" + System.DateTime.Now.ToString()); Console.WriteLine("send message..."); Thread.Sleep(2000); } } } }
View Code

3.測試,開啟服務端和兩個客戶端

可以看出每個服務端為每個客戶端都會創建一個實例對象。

其測試目錄結構如下,不然客戶端遠程對象和服務端會不對應。會報“找不到請求的服務”的異常

 

這就是 Remoting 的三種 激活方式,如有問題歡迎指正。

作者:釋迦苦僧 出處:http://www.cnblogs.com/woxpp/p/3995366.html 本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM