Remoting系列(二)----建立第一个入门程序
Remoting系列(二)----建立第一個(gè)入門程序
下面的Remoting程序,采用了Singleton模式的服務(wù)器端激活的方式,分為三部分。
General:一個(gè)遠(yuǎn)程對(duì)象公用的程序集。
Server:服務(wù)器端
Client:客戶端
一 創(chuàng)建第一個(gè)Remoting控制臺(tái)程序
在創(chuàng)建程序之前,先把幾個(gè)要用到的類先介紹一下:
1) MarshalByRefObject類:
允許在支持遠(yuǎn)程處理的應(yīng)用程序中跨應(yīng)用程序域邊界訪問對(duì)象。
應(yīng)用程序域是一個(gè)操作系統(tǒng)進(jìn)程中一個(gè)或多個(gè)應(yīng)用程序所駐留的分區(qū)。同一應(yīng)用程序域中的對(duì)象直接通信。不同應(yīng)用程序域中的對(duì)象的通信方式有兩種:一種是跨應(yīng)用程序域邊界傳輸對(duì)象副本,一種是使用代理交換消息。
MarshalByRefObject 是通過使用代理交換消息來跨應(yīng)用程序域邊界進(jìn)行通信的對(duì)象的基類。不是從 MarshalByRefObject 繼承的對(duì)象根據(jù)值隱式封送。當(dāng)遠(yuǎn)程應(yīng)用程序引用根據(jù)值封送的對(duì)象時(shí),將跨應(yīng)用程序域邊界傳遞該對(duì)象的副本。
MarshalByRefObject 對(duì)象在本地應(yīng)用程序域的邊界內(nèi)可直接訪問。遠(yuǎn)程應(yīng)用程序域中的應(yīng)用程序首次訪問 MarshalByRefObject 時(shí),會(huì)向該遠(yuǎn)程應(yīng)用程序傳遞代理。對(duì)該代理后面的調(diào)用將封送回駐留在本地應(yīng)用程序域中的對(duì)象。
當(dāng)跨應(yīng)用程序域邊界使用類型時(shí),類型必須是從 MarshalByRefObject 繼承的,而且由于對(duì)象的成員在創(chuàng)建它們的應(yīng)用程序域之外無法使用,所以不得復(fù)制對(duì)象的狀態(tài)。
2) ChannelServices 類:
提供幫助進(jìn)行遠(yuǎn)程處理信道注冊(cè)、解析和 URL 發(fā)現(xiàn)的靜態(tài)方法。
信道跨遠(yuǎn)程處理邊界(例如 AppDomains、進(jìn)程和計(jì)算機(jī))在應(yīng)用程序之間傳輸消息。這些交叉可以是入站和出站的。信道可以在終結(jié)點(diǎn)上偵聽入站消息,向終結(jié)點(diǎn)發(fā)送出站消息,或同時(shí)進(jìn)行這兩種操作。這在運(yùn)行庫中提供一個(gè)可擴(kuò)展性點(diǎn),以便插入各種協(xié)議,即使運(yùn)行庫可能并不在信道的另一端。運(yùn)行庫對(duì)象可用于公開各種語義和實(shí)體。信道提供可擴(kuò)展性點(diǎn)以將消息在特定協(xié)議間來回轉(zhuǎn)換。
3) TcpChannel 類:
提供使用 TCP 協(xié)議傳輸消息的信道實(shí)現(xiàn)。
一) Remoting程序的創(chuàng)建(分三步走)[附源代碼下載].
1 創(chuàng)建General遠(yuǎn)程對(duì)象
此對(duì)象必須繼承MarshalByRefObject。
代碼如下:
?2????///?遠(yuǎn)程對(duì)象類
?3????///?</summary>
?4????public?class?RemoteObject?:?MarshalByRefObject
?5????{
?6????????public?RemoteObject()
?7????????{
?8????????????Console.WriteLine("I?am?from?Remote?Object!");
?9????????}
10????????public?string?GetClassName(string?name)
11????????{
12????????????return?name;
13????????}
14????}
2.創(chuàng)建Server作為"宿主(host)",以接收客戶請(qǐng)求
1)注冊(cè)通道,下文注冊(cè)了一個(gè)端口號(hào)為8000的端口。
?? 注冊(cè)后服務(wù)器就會(huì)監(jiān)聽來自8000端口的請(qǐng)求。
2)注冊(cè)服務(wù)器激活的遠(yuǎn)程對(duì)象
?2????///?服務(wù)器端
?3????///?</summary>
?4????public?class?Server
?5????{
?6????????static?void?Main(string[]?args)
?7????????{
?8????????????//實(shí)例化并注冊(cè)一個(gè)TCP通道
?9????????????IChannel?tcpchannel?=?new?TcpChannel(8000);
10????????????ChannelServices.RegisterChannel(tcpchannel,?true);
11
12????????????//將服務(wù)端上的對(duì)象類型注冊(cè)為已知類型
13????????????RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemoteObject),?"GetObject",?WellKnownObjectMode.Singleton);
14
15????????????Console.WriteLine("Press?Enter?Key?to?Exit!");
16????????????Console.ReadLine();
17??????
18????????}
19????}
3.創(chuàng)建Client,調(diào)用遠(yuǎn)程對(duì)象
1)注冊(cè)通道
2)根據(jù)URL得到對(duì)象代理
3)使用代理調(diào)用遠(yuǎn)程對(duì)象
?2????///?客戶端
?3????///?</summary>
?4????public?class?Client
?5????{
?6????????static?void?Main(string[]?args)
?7????????{
?8????????????//實(shí)例化并注冊(cè)一個(gè)TCP通道
?9????????????IChannel?tcpChannel?=?new?TcpChannel();
10????????????ChannelServices.RegisterChannel(tcpChannel,?true);
11
12????????????//激活遠(yuǎn)程對(duì)象
13????????????RemoteObject?obj?=?(RemoteObject)Activator.GetObject(typeof(RemotingDemo.RemoteObject),"tcp://localhost:8000/GetObject");
14
15????????????if?(obj?==?null)
16????????????{
17????????????????Console.WriteLine("Could?not?get?Tcp?Server");
18????????????}
19
20????????????//調(diào)用遠(yuǎn)程方法
21????????????Console.WriteLine("Client?TCP?GetClassName:?{0}",obj.GetClassName("ring1981"));
22
23????????????Console.ReadLine();
24????????}
25????}
到此為止,Remoting應(yīng)用程序建立完畢!
運(yùn)行結(jié)果:
上面的例子是全部通過編程實(shí)現(xiàn),在下篇文章里里我會(huì)介紹如何通過配置文件實(shí)現(xiàn)。
二)關(guān)于運(yùn)行Remoting程序的一點(diǎn)說明
由于不少初學(xué)者說按"F5"看不到這樣的結(jié)果,其實(shí)是沒有學(xué)會(huì)如何運(yùn)行這種多個(gè)項(xiàng)目,出現(xiàn)多個(gè)Dos窗口結(jié)果的工程。
我就附帶介紹一下如何運(yùn)行上面這個(gè)例子吧:
第一步: 選擇"Debug"->"Start Debuging"或"Debug->Start without Debug"都行,點(diǎn)擊后會(huì)出現(xiàn)一個(gè)Dos窗口顯示結(jié)果。
第二步: 選擇"Soluting Explorer"下的"Client"項(xiàng)目,選中后點(diǎn)擊鼠標(biāo)右鍵,點(diǎn)擊后出現(xiàn)一個(gè)菜單。
第三步: 選擇"Debug"->"Start new instance",單擊就OK了。
?
二 使用配置文件建立Remoting程序
一) 服務(wù)器端配置(app.config)
?1<configuration>?2??<system.runtime.remoting>
?3????<application>
?4??????<channels>
?5????????<channel?ref="tcp"?port="8000"?/>
?6??????</channels>
?7??????<service>
?8????????<wellknown?mode="Singleton"
?9???????????????????type="RemotingDemo.RemoteObject,?General"
10???????????????????objectUri="GetObject"?/>
11??????</service>
12????</application>
13??</system.runtime.remoting>
14</configuration>
15
此時(shí)服務(wù)器端代碼為:
?1?/**////?<summary>
?2????///?服務(wù)器端
?3????///?</summary>
?4????public?class?Server
?5????{
?6????????static?void?Main(string[]?args)
?7????????{????????????
?8????????????RemotingConfiguration.Configure("server.exe.config",?true);
?9
10????????????Console.WriteLine("Press?Enter?Key?to?Exit!");
11????????????Console.ReadLine();??????
12????????}
13????}
二) 客戶端配置 (client.exe.config)
?1<configuration>
?2????<system.runtime.remoting>
?3????????<application>
?4????????????<client>
?5????????????????<wellknown?type="RemoteObject,?General"?url="tcp://localhost:8000/GetObject"?/>
?6????????????</client>
?7????????????<channels>
?8????????????????<channel?ref="tcp"?port="0"></channel>
?9????????????</channels>
10????????</application>
11????</system.runtime.remoting>
12</configuration>
13
此時(shí)客戶端的代碼為:
/**////?<summary>
????///?客戶端
????///?</summary>
????public?class?Client
????{
????????static?void?Main(string[]?args)
????????{
????????????
????????????RemotingConfiguration.Configure(@"client.exe.config",?true);
????????????RemoteObject?obj?=?new?RemoteObject();
????????????if?(obj?==?null)
????????????{
????????????????Console.WriteLine("Could?not?get?Tcp?Server");
????????????}
????????????//調(diào)用遠(yuǎn)程方法
????????????Console.WriteLine("Client?TCP?GetClassName:?{0}",obj.GetClassName("ring1981"));
????????????Console.ReadLine();
????????}
????}
一個(gè)標(biāo)準(zhǔn)寫全的Remoting Configuration文件應(yīng)該是如下結(jié)構(gòu):
?1<configuration>
?2???<system.runtime.remoting>
?3??????<application>
?4????????<lifetime?/>
?5????????<channels?/>
?6????????<service?/>
?7????????<client?/>
?8??????</application>
?9???</system.runtime.remoting>
10</configuration>
11
12
接下來結(jié)合配置文件介紹一下各結(jié)點(diǎn)的具體涉及內(nèi)容:
一) 生命周期(LifeTime):用于配置對(duì)象的生命周期.
| leaseTime | The initial time to live (TTL) for your objects (默認(rèn)5 分鐘) |
| sponsorshipTimeout | The time to wait for a sponsor's reply (默認(rèn)2 分鐘) |
| renewOnCallTime | The time to add to an object's TTL when a method is called (默認(rèn)2 分鐘) |
| leaseManagerPollTime | The interval in which your object's TTL will be checked (默認(rèn)10 秒) |
例子:
1<lifetime
2???leaseTime="90MS"
3???renewOnCallTime="90MS"
4???leaseManagerPollTime="100MS"
5/>
這里MS是毫秒的意思.如果想配置成秒,那就用S;分鐘是M;小時(shí)是H;天是D。
二) 通道:
如果在服務(wù)器端注冊(cè)一個(gè)TCP通道,監(jiān)聽端口為1000,那么就該如下配置:
1<channels>
2???<channel?ref="tcp"?port="1000">
3</channels>
如果是在客戶端,那么port必須為0。
Channel結(jié)點(diǎn)包含如下內(nèi)容:
| ref | 引用先前定義好的通道("tcp"或"http"),或者引用先前在配置文件里定義好的通道 |
| displayName | 此屬性只用于.NET Framework配置工具 |
| type | 該屬性在ref沒有定義時(shí),是托管的。Attribute that is mandatory when ref has not been specified. Contains the exact type (namespace, classname, assembly) of the channel's implementation. When the assembly is in the GAC, you have to specify version, culture, and public key information as well. |
| port | 端口號(hào) |
三) Service:
Service屬性允許你注冊(cè)SAOs和CAOs.該結(jié)點(diǎn)下可以包含多和 <wellknown> 和<activated> 屬性。結(jié)構(gòu)示例如下:
?2??<system.runtime.remoting>
?3????<application>
?4??????<service>
?5??????????<wellknown?/>
?6??????????<activated?/>
?7??????</service>
?8????</application>
?9??</system.runtime.remoting>
10</configuration>
11
12
?
1) WellKnow:
| type | 寫法如"<namespace>.<classname>, <assembly>"。程序集中已發(fā)布類的類型。 |
| mode | 指出具體對(duì)象調(diào)用類型("Singleton" 或"SingleCall"). |
| objectUri | 用于呼叫對(duì)象的終端URI。當(dāng)對(duì)象宿主在IIS中,URI需以.soap或.rem結(jié)尾。 |
| displayName | 用于.NET Framework Configuration Tool中。 |
結(jié)構(gòu)示例如下:
?1<configuration>
?2??<system.runtime.remoting>
?3????<application>
?4??????<channels>
?5????????<channel?ref="http"?port="1234"?/>
?6??????</channels>
?7??????<service>
?8????????<wellknown?mode="Singleton"
?9???????????????????type="Server.CustomerManager,?Server"
10???????????????????objectUri="CustomerManager.soap"?/>
11??????</service>
12
13????</application>
14??</system.runtime.remoting>
15</configuration>
16
?2) Activated:
| type | 寫法如"<namespace>.<classname>, <assembly>"。程序集中已發(fā)布類的類型。 |
結(jié)構(gòu)示例如下:
?1<configuration>
?2???<system.runtime.remoting>
?3??????<application>
?4?????????<channels>
?5????????????<channel?ref="http"?port="1234"?/>
?6?????????</channels>
?7?????????<service>
?8????????????<activated?type="MyObject,?MyAssembly"/>
?9?????????</service>
10??????</application>
11???</system.runtime.remoting>
12</configuration>
13
14
?
四) Client:
與<service>屬性相對(duì),結(jié)構(gòu)與<service>非常類似。
結(jié)構(gòu)示例如下:
?2???<system.runtime.remoting>
?3??????<application>
?4?????????<client>
?5????????????<wellknown?/>
?6????????????<activated?/>
?7????????</client>
?8??????</application>
?9???</system.runtime.remoting>
10</configuration>
11
12
三 Remoting的部署
一) 如何將Remoting部署為Windows Service?
1) 新建一個(gè)windows service項(xiàng)目
2) 在Service1的OnStart()下寫好方法,代碼如下:
2??{
3???RemotingConfiguration.Configure(@"C:\..\WindowsService1.exe.config");
4??}
3)?打開Visual Studio 2005 Command Prompt窗口.
4) 進(jìn)入WindowsService1工程的bin\debug目錄.
???? cd D:\.......\bin\debug
5) 輸入installutil WindowsService1.exe,回車! 安裝完畢!此時(shí)在Windows服務(wù)中,就可以看到新注冊(cè)的服務(wù).
6) 如果要卸載該服務(wù),輸入的命令為 installutil /u WindowsService1.exe.
二) 如何將Remoting部署在IIS中?
1) 將Remoting遠(yuǎn)程對(duì)象項(xiàng)目編譯成程序集
2) 創(chuàng)建虛擬目錄和bin文件夾
3) 將生成的程序集放在bin文件夾下.
4) 編寫一個(gè)web.config,內(nèi)容和Server下的配置文件相似,但不需要<channel>結(jié)點(diǎn).
5) 將web.config放在虛擬目錄下。
完畢! 此時(shí)客戶端就可以訪問遠(yuǎn)程對(duì)象了。
轉(zhuǎn)載于:https://www.cnblogs.com/chinhr/archive/2008/04/16/1155498.html
總結(jié)
以上是生活随笔為你收集整理的Remoting系列(二)----建立第一个入门程序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 远程机房监控设计方案
- 下一篇: 安装和使用Glassfish