.Net組件程序設計之遠程調用(二)編程
引用封送對象激活類型兩種,服務器
一種是客戶端激活類型,一種是服務器端激活.app
客戶端激活對象 tcp
客戶端激活方式:當客戶端建立一個遠程對象時,客戶端獲得的是一個新的實例引用,新的實例能夠在內存中維持狀態,而且可使用參數化構造函數來激活遠程對象。ide
服務器激活模式single-call 函數
SingleCall激活方式:當客戶端使用一個服務器激活方式爲SingleCall的對象時,.NET爲每一個方法調用建立一個新對象,在方法執行完畢後,對象則被銷燬,客戶端雖然維持着對遠程對象的引用,可是真實對象已經被銷燬了。url
服務器激活Singletonspa
Singleton激活方式:全部客戶端共享一個遠程對象。線程
下面爲你們演示幾段示例,就詳細的清楚每一種激活方式的做用了。設計
1 using System.Runtime.Remoting; 2 using System.Runtime.Remoting.Messaging; 3 namespace RemoteServer 4 /// <summary> 5 /// 服務端 6 /// </summary> 7 public class MyClass : MarshalByRefObject 8 { 9 public MyClass() 10 { 11 _count++; 12 string mes = AppDomain.CurrentDomain.FriendlyName; 13 Console.WriteLine(mes); 14 } 15 16 private int _count = 0; 17 18 public event EventHandler NumberChanged; 19 20 public void Count() 21 { 22 _count++; 23 Console.WriteLine(AppDomain.CurrentDomain.FriendlyName + "_" + _count.ToString()); 24 } 25 26 public void OnNumberChanged(int num) 27 { 28 if (NumberChanged != null) 29 { 30 NumberChanged(num, null); 31 } 32 } 33 } 34 35 public class EventMehtodClass : MarshalByRefObject 36 { 37 [OneWay] 38 public void OnNumberChanged(object sender, EventArgs e) 39 { 40 if (sender != null) 41 { 42 Console.WriteLine(sender.ToString()); 43 } 44 } 45 }
1 宿主服務端(服務器端) 2 using System.Runtime.Remoting; 3 using System.Runtime.Remoting.Channels; 4 using System.Runtime.Remoting.Channels.Http; 5 using System.Runtime.Remoting.Channels.Tcp; 6 using System.Runtime.Remoting.Channels.Ipc; 7 using System.Runtime.Remoting.Services; 8 using RemoteServer; 9 10 namespace RemoteServerHost 11 12 #region 編程式 宿主服務端註冊 信道和對象類型 13 Console.WriteLine("開始Tcp註冊信道"); 14 IChannel tcpChannel = new TcpChannel(8003); 15 ChannelServices.RegisterChannel(tcpChannel, false);//註冊Tcp類型信道 16 Console.WriteLine("Tcp信道註冊完成————————————————"); 17 Console.WriteLine("開始 服務器激活類型SingleCall模式的宿主服務器端類型註冊"); 18 RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyClass), "RWCTmyclass",WellKnownObjectMode.SingleCall); 19 Console.WriteLine("類型註冊完成"); 20 #endregion 21 22 Thread.Sleep(new TimeSpan(0, 2, 0)); 23 Console.WriteLine("釋放Tcp信道"); 24 ChannelServices.UnregisterChannel(tcpChannel);
這裏所用的激活方式是 服務器SingleCall激活方式,經過RemotingConfiguration.RegisterWellKnownServiceType()方法來註冊類型,第二個參數爲統一資源標識符(URI),很好理解就是字面的意思,遠程對象就是資源,標識資源的一個符號(名稱),有了它,客戶端在調用遠程對象的時候才知道具體在哪。由於是服務器激活方式因此URI是在包含在註冊類型的方法中的,而若是是客戶端激活類型註冊的話,則使用RemotingConfiguration.RegisterActivatedServiceType(typeof(MyClass));
有的朋友會問了,這樣統一資源標識符不是沒設置嗎?是的,確實沒有設置,客戶端激活類型註冊的時候URI是這樣設置
1 RemotingConfiguration.ApplicationName = "RWCTmyclass";
1 客戶端(調用端) 2 using System.Runtime.Remoting; 3 using System.Runtime.Remoting.Channels; 4 using System.Runtime.Remoting.Channels.Http; 5 using System.Runtime.Remoting.Channels.Tcp; 6 using System.Runtime.Remoting.Channels.Ipc; 7 using System.Runtime.Remoting.Services; 8 using RemoteServer; 9 10 namespace RemoteClient 11 12 #region 編程式本地註冊 13 Thread.Sleep(new TimeSpan(0, 0, 7));//便於調,使當前客戶端線程阻塞7秒,確保宿主服務端已經運行 14 string url = "tcp://localhost:8003/RWCTmyclass"; 15 Console.WriteLine("開始客戶端註冊類型"); 16 RemotingConfiguration.RegisterWellKnownClientType(typeof(MyClass), url); 17 #endregion 18 19 20 //類型使用 21 MyClass myclass = new MyClass(); 22 myclass.Count(); 23 MyClass myclass1 = new MyClass(); 24 myclass1.Count();
圖 1
由於這裏使用的是服務器SingleCall類型模式激活的,因此對象狀態是不保存的,就跟上面那一小節定義的同樣,只有在方法調用的時候纔會被建立,方法調用完畢則會被釋放銷燬,可是也能夠在宿主服務端使用變量來記錄狀態。如今能夠在宿主服務端(服務器端)註冊類型的時候把激活模式換成Singleton的再來看一下結果:
這是編程式的示例代碼,下面給你們演示配置式的。
1 宿主服務端(服務器端) 2 using System.Runtime.Remoting; 3 using System.Runtime.Remoting.Channels; 4 using System.Runtime.Remoting.Channels.Http; 5 using System.Runtime.Remoting.Channels.Tcp; 6 using System.Runtime.Remoting.Channels.Ipc; 7 using System.Runtime.Remoting.Services; 8 9 using System.Threading; 10 11 using RemoteServer; 12 13 namespace RemoteServerHost 14 15 #region 配置式宿主服務端註冊 信道和對象類型 16 Console.WriteLine("開始註冊Http信道"); 17 RemotingConfiguration.Configure(AppDomain.CurrentDomain.FriendlyName + ".config"); 18 Console.WriteLine("Http信道註冊完成————————————————"); 19 #endregion
這裏只要使用.NET給咱們提供的RemotingConfiguration類型中的Configure()方法來加載配置文件就好了,註冊信道的類型,遠程對象的激活方式和模式都是在配置文件中註冊的,來看配置文件信息:
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <system.runtime.remoting> 4 <application> 5 <channels> 6 <channel ref="http" port="8004"/> 7 </channels> 8 <service> 9 <wellknown mode="Singleton" type="RemoteServer.MyClass,RemoteServer" objectUri="RTMyClass" /> 10 </service> 11 </application> 12 </system.runtime.remoting> 13 </configuration>
這裏配置文件中,是準備註冊http類型的信道,而且把遠程對象註冊爲服務器激活類型(wellKnow)Singleton激活模式,宿主服務端的就這麼多,接下來看客戶端的.
1 客戶端 2 using System.Runtime.Remoting; 3 using System.Runtime.Remoting.Channels; 4 using System.Runtime.Remoting.Channels.Http; 5 using System.Runtime.Remoting.Channels.Tcp; 6 using System.Runtime.Remoting.Channels.Ipc; 7 using System.Runtime.Remoting.Services; 8 9 using System.Threading; 10 11 using RemoteServer; 12 13 namespace RemoteClient 14 15 #region 配置式本地註冊 16 Thread.Sleep(new TimeSpan(0, 0, 7)); 17 Console.WriteLine("開始客戶端註冊類型"); 18 RemotingConfiguration.Configure(AppDomain.CurrentDomain.FriendlyName + ".config", false); 19 #endregion 20 //類型使用 21 Console.WriteLine(AppDomain.CurrentDomain.FriendlyName); 22 MyClass myclass = new MyClass(); 23 myclass.Count(); 24 MyClass myclass1 = new MyClass(); 25 myclass1.Count();
跟宿主服務端的同樣,使用Configure()方法來註冊遠程對象,可是本地的配置文件怎麼配置呢?不着急的,一塊兒來看:
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <system.runtime.remoting> 4 <application> 5 <client> 6 <wellknown type="RemoteServer.MyClass,RemoteServer" url="http://localhost:8004/RTMyClass"/> 7 </client> 8 </application> 9 </system.runtime.remoting> 10 </configuration>
客戶端 要註冊的 遠程對象類型 的 激活類型(客戶端激活、服務器端激活) 是要跟宿主服務端的相對應。
此次換了Singleton模式
圖2
1 宿主服務端: 2 using System.Runtime.Remoting; 3 using System.Runtime.Remoting.Channels; 4 using System.Runtime.Remoting.Channels.Http; 5 using System.Runtime.Remoting.Channels.Tcp; 6 using System.Runtime.Remoting.Channels.Ipc; 7 using System.Runtime.Remoting.Services; 8 using System.Threading; 9 10 using RemoteServer; 11 namespace RemoteServerHost 12 13 14 #region 遠程回調 15 Console.WriteLine("開始Tcp註冊信道"); 16 BinaryServerFormatterSinkProvider formatter = new BinaryServerFormatterSinkProvider();//二進制格式化器 17 formatter.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;//設置過濾類型爲Full 18 19 IDictionary channel = new Hashtable(); 20 channel["name"] = "RWCTmyclass"; 21 channel["port"] = 8003; 22 23 IChannel tcpChannel = new TcpChannel(channel, null, formatter); 24 ChannelServices.RegisterChannel(tcpChannel, false);//註冊Tcp類型信道 25 Console.WriteLine("Tcp信道註冊完成————————————————"); 26 Console.WriteLine("開始 服務器激活類型Singleleton模式的宿主服務器端類型註冊"); 27 RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyClass), "RWCTmyclass", WellKnownObjectMode.Singleton); 28 Console.WriteLine("類型註冊完成"); 29 #endregion 30 31 32 Thread.Sleep(new TimeSpan(0, 2, 0)); 33 34 Console.WriteLine("釋放Tcp信道"); 35 ChannelServices.UnregisterChannel(tcpChannel);
1 客戶端: 2 3 using System.Runtime.Remoting; 4 using System.Runtime.Remoting.Channels; 5 using System.Runtime.Remoting.Channels.Http; 6 using System.Runtime.Remoting.Channels.Tcp; 7 using System.Runtime.Remoting.Channels.Ipc; 8 using System.Runtime.Remoting.Services; 9 10 using System.Threading; 11 12 using RemoteServer; 13 14 namespace RemoteClient 15 16 17 #region 遠程回調 18 Thread.Sleep(new TimeSpan(0, 0, 7)); 19 IChannel tcp = new TcpChannel(0); 20 ChannelServices.RegisterChannel(tcp, false); 21 string url = "tcp://localhost:8003/RWCTmyclass"; 22 Console.WriteLine("開始客戶端註冊類型"); 23 RemotingConfiguration.RegisterWellKnownClientType(typeof(MyClass), url); 24 #endregion 25 26 Console.WriteLine(AppDomain.CurrentDomain.FriendlyName); 27 MyClass myclass = new MyClass(); 28 myclass.Count(); 29 EventMehtodClass methodclass = new EventMehtodClass(); 30 myclass.NumberChanged += methodclass.OnNumberChanged; 31 Thread.Sleep(100); 32 myclass.OnNumberChanged(100);
圖-3
在Singleton激活方式下是能夠完成遠程回調的,可是用Singlecall模式的話則不行,由於若是是這樣的話,以前對遠程對象(服務器對象)的操做都沒有狀態保存,上面說到過,Singlecall模式是一來一回則被釋放掉了,本地客戶端僅僅是保留了一個代理。能夠驗證一下:
修改宿主服務端的代碼Singleton改成SingleCall
1 RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyClass), "RWCTmyclass", WellKnownObjectMode.SingleCall);
修改客戶端的代碼 myclass.Count();又新加一句
1 MyClass myclass = new MyClass(); 2 myclass.Count(); 3 myclass.Count(); 4 EventMehtodClass methodclass = new EventMehtodClass(); 5 myclass.NumberChanged += methodclass.OnNumberChanged; 6 Thread.Sleep(100); 7 myclass.OnNumberChanged(100);
修改後的運行結果:
圖4
爲何沒有像圖1中的那樣發生回調這裏已經不用說明了。
做者:金源
出處:http://www.cnblogs.com/jin-yuan/
本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面