.Net組件程序設計之遠程調用(二)

 .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     }

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 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的再來看一下結果:
這是編程式的示例代碼,下面給你們演示配置式的。

3.配置式:

 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

4.遠程回調

 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/

本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面

相關文章
相關標籤/搜索