一步一步学Remoting之二:激活模式
生活随笔
收集整理的這篇文章主要介紹了
一步一步学Remoting之二:激活模式
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
遠程對象的激活模式分服務端激活和客戶端激活兩種,(也就是對象分服務端激活對象或者說是知名對象和客戶端激活對象兩種)先看看msdn怎么描述服務端激活的:
服務器激活的對象是其生存期由服務器直接控制的對象。服務器應用程序域只有在客戶端在對象上進行方法調用時才創建這些對象,而不會在客戶端調用?new?或?Activator.GetObject?時創建這些對象;這節省了僅為創建實例而進行的一次網絡往返過程。客戶端請求服務器激活的類型實例時,只在客戶端應用程序域中創建一個代理。然而,這也意味著當您使用默認實現時,只允許對服務器激活的類型使用默認構造函數。若要發布其實例將使用帶參數的特定構造函數創建的類型,可以使用客戶端激活或者動態地發布您的特定實例。
服務器激活的對象有兩種激活模式(或?WellKnownObjectMode?值):Singleton?和?SingleCall。
Singleton?類型任何時候都不會同時具有多個實例。如果存在實例,所有客戶端請求都由該實例提供服務。如果不存在實例,服務器將創建一個實例,而所有后繼的客戶端請求都將由該實例來提供服務。由于?Singleton?類型具有關聯的默認生存期,即使任何時候都不會有一個以上的可用實例,客戶端也不會總接收到對可遠程處理的類的同一實例的引用。
SingleCall?類型對于每個客戶端請求始終只有一個實例。下一個方法調用將由另一個服務器實例提供服務,即使上一個實例尚未被系統回收。SingleCall?類型不參與生存期租約系統。
首先對于服務端激活的兩種模式來做一個試驗,我們把遠程對象做如下的修改:
using?System;
namespace?RemoteObject
{
????public?class?MyObject:MarshalByRefObject
????{
????????private?int?i=0;
????????public?int?Add(int?a,int?b)
????????{
????????????return?a+b;
????????}
????????public?int?Count()
????????{
????????????return?++i;
????????}
????}
}
對客戶端做以下修改:
RemoteObject.MyObject?app?=?(RemoteObject.MyObject)Activator.GetObject(typeof(RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"]);
????????????Console.WriteLine(app.Count());
????????????Console.ReadLine();
第一次打開客戶端的時候顯示1,第二次打開的時候顯示2,類推……由此驗證了Singleton?類型任何時候都不會同時具有多個實例。如果存在實例,所有客戶端請求都由該實例提供服務。如果不存在實例,服務器將創建一個實例,而所有后繼的客戶端請求都將由該實例來提供服務。
把服務器端的config修改一下:
<wellknown?type="RemoteObject.MyObject,RemoteObject"?objectUri="RemoteObject.MyObject"
????????????????????mode="SingleCall"?/>
(這里注意大小寫,大寫的C)
再重新運行服務端和客戶端,打開多個客戶端發現始終顯示1。由此驗證了SingleCall?類型對于每個客戶端請求始終只有一個實例。下一個方法調用將由另一個服務器實例提供服務。
下面再說一下客戶端的激活模式,msdn中這么寫:
客戶端激活的對象是其生存期由調用應用程序域控制的對象,正如對象對于客戶端是本地對象時對象的生存期由調用應用程序域控制一樣。對于客戶端激活,當客戶端試圖創建服務器對象的實例時發生一個到服務器的往返過程,而客戶端代理是使用對象引用?(ObjRef)?創建的,該對象引用是從在服務器上創建遠程對象返回時獲取的。每當客戶端創建客戶端激活的類型的實例時,該實例都將只服務于該特定客戶端中的特定引用,直到其租約到期并回收其內存為止。如果調用應用程序域創建兩個遠程類型的新實例,每個客戶端引用都將只調用從其中返回引用的服務器應用程序域中的特定實例。
理解一下,可以歸納出
1、客戶端激活的時間是在客戶端請求的時候,而服務端激活遠程對象的時間是在調用對象方法的時候
遠程對象修改如下:
using?System;
namespace?RemoteObject
{
????public?class?MyObject:MarshalByRefObject
????{
????????private?int?i=0;
????????public?MyObject()
????????{
????????????Console.WriteLine("激活");
????????}
????????public?int?Add(int?a,int?b)
????????{
????????????return?a+b;
????????}
????????public?int?Count()
????????{
????????????return?++i;
????????}
????}
}
服務端配置文件:
<configuration>
????<system.runtime.remoting>
????????<application?name="RemoteServer">
????????????<service>
????????????????<activated?type="RemoteObject.MyObject,RemoteObject"/>
????????????</service>
????????????<channels>
????????????????<channel?ref="tcp"?port="9999"/>
????????????</channels>
????????</application>
????</system.runtime.remoting>
</configuration>
客戶端程序:
using?System;
namespace?RemoteClient
{
????class?MyClient
????{
????????[STAThread]
????????static?void?Main(string[]?args)
????????{
????????????//RemoteObject.MyObject?app?=?(RemoteObject.MyObject)Activator.GetObject(typeof(RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"]);
????????????RemoteObject.MyObject?app=(RemoteObject.MyObject)Activator.CreateInstance(typeof(RemoteObject.MyObject),null,new?object[]{new?System.Runtime.Remoting.Activation.UrlAttribute(System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"])});
????????????//Console.WriteLine(app.Count());
????????????Console.ReadLine();
????????}
????}
}
客戶端配置文件:
<configuration>
?<appSettings>
?<add?key="ServiceURL"?value="tcp://localhost:9999/RemoteServer"/>
?</appSettings>
</configuration>
(這里的uri按照服務端配置文件中application元素定義的RemoteServer來寫)
運行程序可以看到,在客戶端啟動的時候服務端就輸出了“激活”,我們再轉回知名模式進行測試發現只有運行了方法才會在服務端輸出“激活”。
2、客戶端激活可以調用自定義的構造方法,而不像服務端激活只能使用默認的構造方法
把客戶端代碼修改如下:
RemoteObject.MyObject?app=(RemoteObject.MyObject)Activator.CreateInstance(typeof(RemoteObject.MyObject),new?object[]{10},new?object[]{new?System.Runtime.Remoting.Activation.UrlAttribute(System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"])});
????????????Console.WriteLine(app.Count());
這里看到我們在CreateInstance方法的第二個參數中提供了10作為構造方法的參數。在服務端激活模式我們不能這么做。
遠程對象構造方法修改如下:
public?MyObject(int?k)
????????{
????????????this.i=k;
????????????Console.WriteLine("激活");
????????}
毫無疑問,我們運行客戶端發現輸出的是11而不是1了。
3、通過上面的例子,我們運行多個客戶端發現出現的永遠是11,因此,客戶端激活模式一旦獲得客戶端的請求,將為每一個客戶端都建立一個實例引用。
總結:
1、?Remoting支持兩種遠程對象:知名的和客戶激活的。知名的遠程對象使用了uri作為標識,客戶程序使用這個uri來訪問那些遠程對象,也正式為什么稱作知名的原因。對知名的對象來說2種使用模式:SingleCall和Singleton,對于前者每次調用都會新建對象,因此對象是無狀態的。對于后者,對象只被創建一次,所有客戶共享對象狀態,因此對象是有狀態的。另外一種客戶端激活對象使用類的類型來激活,uri再后臺被動態創建,并且返回給客戶程序。客戶激活對象是有狀態的。
2、對于Singleton對象來說需要考慮伸縮性,Singleton對象不能在多個服務器上被部署,如果要跨服務器就不能使用Singleton了。
備注:個人習慣原因,在我的例子中服務端的配置都是用config文件的,客戶端的配置都是基本用程序方式的
使用配置文件的優點:無需重新編譯就可以配置通道和遠程對象,編寫的代碼量比較少
使用程序定制的優點:可以獲得運行期間的信息,對程序調試有利。
using?System;
namespace?RemoteObject
{
????public?class?MyObject:MarshalByRefObject
????{
????????private?int?i=0;
????????public?int?Add(int?a,int?b)
????????{
????????????return?a+b;
????????}
????????public?int?Count()
????????{
????????????return?++i;
????????}
????}
}
對客戶端做以下修改:
RemoteObject.MyObject?app?=?(RemoteObject.MyObject)Activator.GetObject(typeof(RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"]);
????????????Console.WriteLine(app.Count());
????????????Console.ReadLine();
第一次打開客戶端的時候顯示1,第二次打開的時候顯示2,類推……由此驗證了Singleton?類型任何時候都不會同時具有多個實例。如果存在實例,所有客戶端請求都由該實例提供服務。如果不存在實例,服務器將創建一個實例,而所有后繼的客戶端請求都將由該實例來提供服務。
把服務器端的config修改一下:
<wellknown?type="RemoteObject.MyObject,RemoteObject"?objectUri="RemoteObject.MyObject"
????????????????????mode="SingleCall"?/>
(這里注意大小寫,大寫的C)
再重新運行服務端和客戶端,打開多個客戶端發現始終顯示1。由此驗證了SingleCall?類型對于每個客戶端請求始終只有一個實例。下一個方法調用將由另一個服務器實例提供服務。
下面再說一下客戶端的激活模式,msdn中這么寫:
客戶端激活的對象是其生存期由調用應用程序域控制的對象,正如對象對于客戶端是本地對象時對象的生存期由調用應用程序域控制一樣。對于客戶端激活,當客戶端試圖創建服務器對象的實例時發生一個到服務器的往返過程,而客戶端代理是使用對象引用?(ObjRef)?創建的,該對象引用是從在服務器上創建遠程對象返回時獲取的。每當客戶端創建客戶端激活的類型的實例時,該實例都將只服務于該特定客戶端中的特定引用,直到其租約到期并回收其內存為止。如果調用應用程序域創建兩個遠程類型的新實例,每個客戶端引用都將只調用從其中返回引用的服務器應用程序域中的特定實例。
理解一下,可以歸納出
1、客戶端激活的時間是在客戶端請求的時候,而服務端激活遠程對象的時間是在調用對象方法的時候
遠程對象修改如下:
using?System;
namespace?RemoteObject
{
????public?class?MyObject:MarshalByRefObject
????{
????????private?int?i=0;
????????public?MyObject()
????????{
????????????Console.WriteLine("激活");
????????}
????????public?int?Add(int?a,int?b)
????????{
????????????return?a+b;
????????}
????????public?int?Count()
????????{
????????????return?++i;
????????}
????}
}
服務端配置文件:
<configuration>
????<system.runtime.remoting>
????????<application?name="RemoteServer">
????????????<service>
????????????????<activated?type="RemoteObject.MyObject,RemoteObject"/>
????????????</service>
????????????<channels>
????????????????<channel?ref="tcp"?port="9999"/>
????????????</channels>
????????</application>
????</system.runtime.remoting>
</configuration>
客戶端程序:
using?System;
namespace?RemoteClient
{
????class?MyClient
????{
????????[STAThread]
????????static?void?Main(string[]?args)
????????{
????????????//RemoteObject.MyObject?app?=?(RemoteObject.MyObject)Activator.GetObject(typeof(RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"]);
????????????RemoteObject.MyObject?app=(RemoteObject.MyObject)Activator.CreateInstance(typeof(RemoteObject.MyObject),null,new?object[]{new?System.Runtime.Remoting.Activation.UrlAttribute(System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"])});
????????????//Console.WriteLine(app.Count());
????????????Console.ReadLine();
????????}
????}
}
客戶端配置文件:
<configuration>
?<appSettings>
?<add?key="ServiceURL"?value="tcp://localhost:9999/RemoteServer"/>
?</appSettings>
</configuration>
(這里的uri按照服務端配置文件中application元素定義的RemoteServer來寫)
運行程序可以看到,在客戶端啟動的時候服務端就輸出了“激活”,我們再轉回知名模式進行測試發現只有運行了方法才會在服務端輸出“激活”。
2、客戶端激活可以調用自定義的構造方法,而不像服務端激活只能使用默認的構造方法
把客戶端代碼修改如下:
RemoteObject.MyObject?app=(RemoteObject.MyObject)Activator.CreateInstance(typeof(RemoteObject.MyObject),new?object[]{10},new?object[]{new?System.Runtime.Remoting.Activation.UrlAttribute(System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"])});
????????????Console.WriteLine(app.Count());
這里看到我們在CreateInstance方法的第二個參數中提供了10作為構造方法的參數。在服務端激活模式我們不能這么做。
遠程對象構造方法修改如下:
public?MyObject(int?k)
????????{
????????????this.i=k;
????????????Console.WriteLine("激活");
????????}
毫無疑問,我們運行客戶端發現輸出的是11而不是1了。
3、通過上面的例子,我們運行多個客戶端發現出現的永遠是11,因此,客戶端激活模式一旦獲得客戶端的請求,將為每一個客戶端都建立一個實例引用。
總結:
1、?Remoting支持兩種遠程對象:知名的和客戶激活的。知名的遠程對象使用了uri作為標識,客戶程序使用這個uri來訪問那些遠程對象,也正式為什么稱作知名的原因。對知名的對象來說2種使用模式:SingleCall和Singleton,對于前者每次調用都會新建對象,因此對象是無狀態的。對于后者,對象只被創建一次,所有客戶共享對象狀態,因此對象是有狀態的。另外一種客戶端激活對象使用類的類型來激活,uri再后臺被動態創建,并且返回給客戶程序。客戶激活對象是有狀態的。
2、對于Singleton對象來說需要考慮伸縮性,Singleton對象不能在多個服務器上被部署,如果要跨服務器就不能使用Singleton了。
備注:個人習慣原因,在我的例子中服務端的配置都是用config文件的,客戶端的配置都是基本用程序方式的
使用配置文件的優點:無需重新編譯就可以配置通道和遠程對象,編寫的代碼量比較少
使用程序定制的優點:可以獲得運行期間的信息,對程序調試有利。
服務器激活的對象是其生存期由服務器直接控制的對象。服務器應用程序域只有在客戶端在對象上進行方法調用時才創建這些對象,而不會在客戶端調用?new?或?Activator.GetObject?時創建這些對象;這節省了僅為創建實例而進行的一次網絡往返過程。客戶端請求服務器激活的類型實例時,只在客戶端應用程序域中創建一個代理。然而,這也意味著當您使用默認實現時,只允許對服務器激活的類型使用默認構造函數。若要發布其實例將使用帶參數的特定構造函數創建的類型,可以使用客戶端激活或者動態地發布您的特定實例。
服務器激活的對象有兩種激活模式(或?WellKnownObjectMode?值):Singleton?和?SingleCall。
Singleton?類型任何時候都不會同時具有多個實例。如果存在實例,所有客戶端請求都由該實例提供服務。如果不存在實例,服務器將創建一個實例,而所有后繼的客戶端請求都將由該實例來提供服務。由于?Singleton?類型具有關聯的默認生存期,即使任何時候都不會有一個以上的可用實例,客戶端也不會總接收到對可遠程處理的類的同一實例的引用。
SingleCall?類型對于每個客戶端請求始終只有一個實例。下一個方法調用將由另一個服務器實例提供服務,即使上一個實例尚未被系統回收。SingleCall?類型不參與生存期租約系統。
首先對于服務端激活的兩種模式來做一個試驗,我們把遠程對象做如下的修改:
using?System;
namespace?RemoteObject
{
????public?class?MyObject:MarshalByRefObject
????{
????????private?int?i=0;
????????public?int?Add(int?a,int?b)
????????{
????????????return?a+b;
????????}
????????public?int?Count()
????????{
????????????return?++i;
????????}
????}
}
對客戶端做以下修改:
RemoteObject.MyObject?app?=?(RemoteObject.MyObject)Activator.GetObject(typeof(RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"]);
????????????Console.WriteLine(app.Count());
????????????Console.ReadLine();
第一次打開客戶端的時候顯示1,第二次打開的時候顯示2,類推……由此驗證了Singleton?類型任何時候都不會同時具有多個實例。如果存在實例,所有客戶端請求都由該實例提供服務。如果不存在實例,服務器將創建一個實例,而所有后繼的客戶端請求都將由該實例來提供服務。
把服務器端的config修改一下:
<wellknown?type="RemoteObject.MyObject,RemoteObject"?objectUri="RemoteObject.MyObject"
????????????????????mode="SingleCall"?/>
(這里注意大小寫,大寫的C)
再重新運行服務端和客戶端,打開多個客戶端發現始終顯示1。由此驗證了SingleCall?類型對于每個客戶端請求始終只有一個實例。下一個方法調用將由另一個服務器實例提供服務。
下面再說一下客戶端的激活模式,msdn中這么寫:
客戶端激活的對象是其生存期由調用應用程序域控制的對象,正如對象對于客戶端是本地對象時對象的生存期由調用應用程序域控制一樣。對于客戶端激活,當客戶端試圖創建服務器對象的實例時發生一個到服務器的往返過程,而客戶端代理是使用對象引用?(ObjRef)?創建的,該對象引用是從在服務器上創建遠程對象返回時獲取的。每當客戶端創建客戶端激活的類型的實例時,該實例都將只服務于該特定客戶端中的特定引用,直到其租約到期并回收其內存為止。如果調用應用程序域創建兩個遠程類型的新實例,每個客戶端引用都將只調用從其中返回引用的服務器應用程序域中的特定實例。
理解一下,可以歸納出
1、客戶端激活的時間是在客戶端請求的時候,而服務端激活遠程對象的時間是在調用對象方法的時候
遠程對象修改如下:
using?System;
namespace?RemoteObject
{
????public?class?MyObject:MarshalByRefObject
????{
????????private?int?i=0;
????????public?MyObject()
????????{
????????????Console.WriteLine("激活");
????????}
????????public?int?Add(int?a,int?b)
????????{
????????????return?a+b;
????????}
????????public?int?Count()
????????{
????????????return?++i;
????????}
????}
}
服務端配置文件:
<configuration>
????<system.runtime.remoting>
????????<application?name="RemoteServer">
????????????<service>
????????????????<activated?type="RemoteObject.MyObject,RemoteObject"/>
????????????</service>
????????????<channels>
????????????????<channel?ref="tcp"?port="9999"/>
????????????</channels>
????????</application>
????</system.runtime.remoting>
</configuration>
客戶端程序:
using?System;
namespace?RemoteClient
{
????class?MyClient
????{
????????[STAThread]
????????static?void?Main(string[]?args)
????????{
????????????//RemoteObject.MyObject?app?=?(RemoteObject.MyObject)Activator.GetObject(typeof(RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"]);
????????????RemoteObject.MyObject?app=(RemoteObject.MyObject)Activator.CreateInstance(typeof(RemoteObject.MyObject),null,new?object[]{new?System.Runtime.Remoting.Activation.UrlAttribute(System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"])});
????????????//Console.WriteLine(app.Count());
????????????Console.ReadLine();
????????}
????}
}
客戶端配置文件:
<configuration>
?<appSettings>
?<add?key="ServiceURL"?value="tcp://localhost:9999/RemoteServer"/>
?</appSettings>
</configuration>
(這里的uri按照服務端配置文件中application元素定義的RemoteServer來寫)
運行程序可以看到,在客戶端啟動的時候服務端就輸出了“激活”,我們再轉回知名模式進行測試發現只有運行了方法才會在服務端輸出“激活”。
2、客戶端激活可以調用自定義的構造方法,而不像服務端激活只能使用默認的構造方法
把客戶端代碼修改如下:
RemoteObject.MyObject?app=(RemoteObject.MyObject)Activator.CreateInstance(typeof(RemoteObject.MyObject),new?object[]{10},new?object[]{new?System.Runtime.Remoting.Activation.UrlAttribute(System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"])});
????????????Console.WriteLine(app.Count());
這里看到我們在CreateInstance方法的第二個參數中提供了10作為構造方法的參數。在服務端激活模式我們不能這么做。
遠程對象構造方法修改如下:
public?MyObject(int?k)
????????{
????????????this.i=k;
????????????Console.WriteLine("激活");
????????}
毫無疑問,我們運行客戶端發現輸出的是11而不是1了。
3、通過上面的例子,我們運行多個客戶端發現出現的永遠是11,因此,客戶端激活模式一旦獲得客戶端的請求,將為每一個客戶端都建立一個實例引用。
總結:
1、?Remoting支持兩種遠程對象:知名的和客戶激活的。知名的遠程對象使用了uri作為標識,客戶程序使用這個uri來訪問那些遠程對象,也正式為什么稱作知名的原因。對知名的對象來說2種使用模式:SingleCall和Singleton,對于前者每次調用都會新建對象,因此對象是無狀態的。對于后者,對象只被創建一次,所有客戶共享對象狀態,因此對象是有狀態的。另外一種客戶端激活對象使用類的類型來激活,uri再后臺被動態創建,并且返回給客戶程序。客戶激活對象是有狀態的。
2、對于Singleton對象來說需要考慮伸縮性,Singleton對象不能在多個服務器上被部署,如果要跨服務器就不能使用Singleton了。
備注:個人習慣原因,在我的例子中服務端的配置都是用config文件的,客戶端的配置都是基本用程序方式的
使用配置文件的優點:無需重新編譯就可以配置通道和遠程對象,編寫的代碼量比較少
使用程序定制的優點:可以獲得運行期間的信息,對程序調試有利。
using?System;
namespace?RemoteObject
{
????public?class?MyObject:MarshalByRefObject
????{
????????private?int?i=0;
????????public?int?Add(int?a,int?b)
????????{
????????????return?a+b;
????????}
????????public?int?Count()
????????{
????????????return?++i;
????????}
????}
}
對客戶端做以下修改:
RemoteObject.MyObject?app?=?(RemoteObject.MyObject)Activator.GetObject(typeof(RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"]);
????????????Console.WriteLine(app.Count());
????????????Console.ReadLine();
第一次打開客戶端的時候顯示1,第二次打開的時候顯示2,類推……由此驗證了Singleton?類型任何時候都不會同時具有多個實例。如果存在實例,所有客戶端請求都由該實例提供服務。如果不存在實例,服務器將創建一個實例,而所有后繼的客戶端請求都將由該實例來提供服務。
把服務器端的config修改一下:
<wellknown?type="RemoteObject.MyObject,RemoteObject"?objectUri="RemoteObject.MyObject"
????????????????????mode="SingleCall"?/>
(這里注意大小寫,大寫的C)
再重新運行服務端和客戶端,打開多個客戶端發現始終顯示1。由此驗證了SingleCall?類型對于每個客戶端請求始終只有一個實例。下一個方法調用將由另一個服務器實例提供服務。
下面再說一下客戶端的激活模式,msdn中這么寫:
客戶端激活的對象是其生存期由調用應用程序域控制的對象,正如對象對于客戶端是本地對象時對象的生存期由調用應用程序域控制一樣。對于客戶端激活,當客戶端試圖創建服務器對象的實例時發生一個到服務器的往返過程,而客戶端代理是使用對象引用?(ObjRef)?創建的,該對象引用是從在服務器上創建遠程對象返回時獲取的。每當客戶端創建客戶端激活的類型的實例時,該實例都將只服務于該特定客戶端中的特定引用,直到其租約到期并回收其內存為止。如果調用應用程序域創建兩個遠程類型的新實例,每個客戶端引用都將只調用從其中返回引用的服務器應用程序域中的特定實例。
理解一下,可以歸納出
1、客戶端激活的時間是在客戶端請求的時候,而服務端激活遠程對象的時間是在調用對象方法的時候
遠程對象修改如下:
using?System;
namespace?RemoteObject
{
????public?class?MyObject:MarshalByRefObject
????{
????????private?int?i=0;
????????public?MyObject()
????????{
????????????Console.WriteLine("激活");
????????}
????????public?int?Add(int?a,int?b)
????????{
????????????return?a+b;
????????}
????????public?int?Count()
????????{
????????????return?++i;
????????}
????}
}
服務端配置文件:
<configuration>
????<system.runtime.remoting>
????????<application?name="RemoteServer">
????????????<service>
????????????????<activated?type="RemoteObject.MyObject,RemoteObject"/>
????????????</service>
????????????<channels>
????????????????<channel?ref="tcp"?port="9999"/>
????????????</channels>
????????</application>
????</system.runtime.remoting>
</configuration>
客戶端程序:
using?System;
namespace?RemoteClient
{
????class?MyClient
????{
????????[STAThread]
????????static?void?Main(string[]?args)
????????{
????????????//RemoteObject.MyObject?app?=?(RemoteObject.MyObject)Activator.GetObject(typeof(RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"]);
????????????RemoteObject.MyObject?app=(RemoteObject.MyObject)Activator.CreateInstance(typeof(RemoteObject.MyObject),null,new?object[]{new?System.Runtime.Remoting.Activation.UrlAttribute(System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"])});
????????????//Console.WriteLine(app.Count());
????????????Console.ReadLine();
????????}
????}
}
客戶端配置文件:
<configuration>
?<appSettings>
?<add?key="ServiceURL"?value="tcp://localhost:9999/RemoteServer"/>
?</appSettings>
</configuration>
(這里的uri按照服務端配置文件中application元素定義的RemoteServer來寫)
運行程序可以看到,在客戶端啟動的時候服務端就輸出了“激活”,我們再轉回知名模式進行測試發現只有運行了方法才會在服務端輸出“激活”。
2、客戶端激活可以調用自定義的構造方法,而不像服務端激活只能使用默認的構造方法
把客戶端代碼修改如下:
RemoteObject.MyObject?app=(RemoteObject.MyObject)Activator.CreateInstance(typeof(RemoteObject.MyObject),new?object[]{10},new?object[]{new?System.Runtime.Remoting.Activation.UrlAttribute(System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"])});
????????????Console.WriteLine(app.Count());
這里看到我們在CreateInstance方法的第二個參數中提供了10作為構造方法的參數。在服務端激活模式我們不能這么做。
遠程對象構造方法修改如下:
public?MyObject(int?k)
????????{
????????????this.i=k;
????????????Console.WriteLine("激活");
????????}
毫無疑問,我們運行客戶端發現輸出的是11而不是1了。
3、通過上面的例子,我們運行多個客戶端發現出現的永遠是11,因此,客戶端激活模式一旦獲得客戶端的請求,將為每一個客戶端都建立一個實例引用。
總結:
1、?Remoting支持兩種遠程對象:知名的和客戶激活的。知名的遠程對象使用了uri作為標識,客戶程序使用這個uri來訪問那些遠程對象,也正式為什么稱作知名的原因。對知名的對象來說2種使用模式:SingleCall和Singleton,對于前者每次調用都會新建對象,因此對象是無狀態的。對于后者,對象只被創建一次,所有客戶共享對象狀態,因此對象是有狀態的。另外一種客戶端激活對象使用類的類型來激活,uri再后臺被動態創建,并且返回給客戶程序。客戶激活對象是有狀態的。
2、對于Singleton對象來說需要考慮伸縮性,Singleton對象不能在多個服務器上被部署,如果要跨服務器就不能使用Singleton了。
備注:個人習慣原因,在我的例子中服務端的配置都是用config文件的,客戶端的配置都是基本用程序方式的
使用配置文件的優點:無需重新編譯就可以配置通道和遠程對象,編寫的代碼量比較少
使用程序定制的優點:可以獲得運行期間的信息,對程序調試有利。
轉載于:https://www.cnblogs.com/nbwzy/archive/2007/05/31/765756.html
總結
以上是生活随笔為你收集整理的一步一步学Remoting之二:激活模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手把手教你用Pandas读取所有主流数据
- 下一篇: 近日的思绪(外三首)