在msdn中可以找到相關(guān)文章:
http://www.microsoft.com/china/msdn/library/architecture/architecture/architecturetopic/BuildSucApp/BSAAsecmodsecmod29.mspx
http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cpguide/html/cpconRemotingExampleHostingInIIS.asp
可能大家會(huì)覺(jué)得這個(gè)過(guò)程將是一個(gè)復(fù)雜的過(guò)程,其實(shí)不然,下面說(shuō)一下實(shí)現(xiàn)方法,步驟非常少。
先來(lái)建立遠(yuǎn)程對(duì)象
using ?System.Data;
using ?System.Data.SqlClient;
namespace ?RemoteObject?
{?
???? public ? class ?MyObject:MarshalByRefObject?
????{?
???????? public ?DataSet?GetData()
????????{
????????????SqlConnection?conn = new ?SqlConnection(System.Configuration.ConfigurationSettings.AppSettings[ " strconn " ]);
????????????SqlDataAdapter?da = new ?SqlDataAdapter( " select?*?from?UBI_ProvinceMaster " ,conn);
????????????DataSet?ds = new ?DataSet();
????????????da.Fill(ds);
???????????? return ?ds;
????????}
????}
}?
客戶端仍然是一個(gè)控制臺(tái)來(lái)進(jìn)行測(cè)試:
????????????DataTable?dt = app.GetData().Tables[ 0 ];
???????????? foreach (DataRow?dr? in ?dt.Rows)
????????????{
????????????????Console.WriteLine(dr[ " iPrMId " ] + " ? " + dr[ " vPrMName " ]);
????????????}
????????????Console.ReadLine();
服務(wù)端配置文件:
???? < appSettings >
???????????? < add? key ="strconn" ?value ="server=(local);uid=sa;pwd=;database=UBISOFT" ? />
???? </ appSettings >
???? < system .runtime.remoting >
???????? < application? name ="RemoteServer" >
???????????? < service >
???????????????? < wellknown? type ="RemoteObject.MyObject,RemoteObject" ?objectUri ="RemoteObject.MyObject"
????????????????????mode ="SingleCall" ? />
???????????? </ service >
???????????? < channels >
???????????????? < channel? ref ="tcp" ?port ="9999" />
???????????? </ channels >
???????? </ application >
???? </ system.runtime.remoting >
</ configuration >
運(yùn)行程序,我們得到的是一個(gè)省市的列表:

一、windows服務(wù)承載
用vs.net制作一個(gè)windows服務(wù)的過(guò)程基本不超過(guò)10個(gè)步驟,所以我們不需要害怕。
1、建立一個(gè)新的windows服務(wù)項(xiàng)目RemoteServer1
2、打開(kāi)Service1代碼視圖,找到OnStart部分,加入代碼
config和控制臺(tái)方式的config是一樣的,我們讓這個(gè)windows服務(wù)做的僅僅是從config文件讀出配置信息進(jìn)行配置通道。別忘記添加配置文件。
3、切換到設(shè)計(jì)視圖,右鍵-添加安裝程序
4、切換到新生成的ProjectInstaller.cs設(shè)計(jì)視圖,找到serviceProcessInstaller1對(duì)Account屬性設(shè)置為L(zhǎng)ocalSystem,對(duì)serviceInstaller1的ServiceName屬性設(shè)置為RemoteServer1(服務(wù)的名字),StartType屬性設(shè)置為Automatic(系統(tǒng)啟動(dòng)的時(shí)候自動(dòng)啟動(dòng)服務(wù))
5、別忘記對(duì)添加RemoteObject的引用
6、建立一個(gè)新的安裝項(xiàng)目RemoteServerSetup(我們?yōu)閯偛拍莻€(gè)服務(wù)建立一個(gè)安裝項(xiàng)目)
7、右鍵-添加-項(xiàng)目輸出-主輸出-選擇RemoteService1-確定
8、右鍵-視圖-自定義操作-自定義操作上右鍵-添加自定義操作-打開(kāi)應(yīng)用程序文件夾-選擇剛才那個(gè)主輸出-確定
9、重新生成這個(gè)安裝項(xiàng)目-右鍵-安裝
10、在服務(wù)管理器中(我的電腦-右鍵-管理-服務(wù)和應(yīng)用程序-服務(wù))找到RemoteServer1服務(wù),啟動(dòng)服務(wù)
現(xiàn)在就可以打開(kāi)客戶端測(cè)試了!
一些FAQ:
1、啟動(dòng)服務(wù)的時(shí)候系統(tǒng)說(shuō)了類似“服務(wù)什么都沒(méi)有做,服務(wù)已經(jīng)被停止”表示什么?
表示windows服務(wù)出錯(cuò)了,一般是服務(wù)的程序有問(wèn)題,檢查服務(wù)做了什么?在我們這個(gè)程序中僅僅添加了一行代碼,一般不會(huì)出現(xiàn)這個(gè)錯(cuò)誤。
2、運(yùn)行客戶端出現(xiàn)“服務(wù)器無(wú)響應(yīng)”?
先檢查windows服務(wù)配置文件是不是正確設(shè)置了激活方式和激活對(duì)象,客戶端服務(wù)端端口號(hào)是否統(tǒng)一?
3、運(yùn)行客戶端出現(xiàn)“無(wú)法找到程序集”?
檢查windows服務(wù)配置文件是否正確配置了激活對(duì)象的類型和uri?服務(wù)是否添加了遠(yuǎn)程對(duì)象引用?
4、遠(yuǎn)程對(duì)象類中有用到System.Configuration.ConfigurationSettings.AppSettings["strconn"],但是遠(yuǎn)程對(duì)象并沒(méi)有配置文件,它從哪里讀取這個(gè)config的?
因?yàn)檫h(yuǎn)程對(duì)象不是獨(dú)立存在的,它是被windows服務(wù)承載的,因此它從windows服務(wù)的配置文件中讀取一些配置信息,遠(yuǎn)程對(duì)象本生不需要配置文件。
5、安裝的時(shí)候是不是要卸載服務(wù)?
不需要,安裝程序會(huì) 停止服務(wù)端-》卸載服務(wù)-》安裝服務(wù)
6、在正式使用的時(shí)候怎么部署我們的系統(tǒng)?
如果客戶端是程序僅僅只要把安裝項(xiàng)目下面3個(gè)文件傳到服務(wù)器進(jìn)行安裝,配置好config文件(比如連接字符串),開(kāi)啟服務(wù)即可。如果客戶端是網(wǎng)站,同樣把服務(wù)在服務(wù)器安裝,配置好config文件(比如連接字符串),開(kāi)啟服務(wù),最后把網(wǎng)站傳到web服務(wù)器(可能和service不是同一個(gè)服務(wù)器)。
7、部署的時(shí)候需要傳遠(yuǎn)程對(duì)象dll嗎?
不需要,可以看到安裝項(xiàng)目中已經(jīng)自動(dòng)存在了這個(gè)dll。
8、這樣的系統(tǒng)有什么特點(diǎn)?
一個(gè)web服務(wù)器,多個(gè)service服務(wù)器,多個(gè)sqlservice服務(wù)器,web服務(wù)器負(fù)擔(dān)比較小,所有的邏輯代碼都分布到不同的service服務(wù)器上面。
最后說(shuō)一個(gè)測(cè)試的tip:
如果我們遠(yuǎn)程調(diào)用對(duì)象進(jìn)行測(cè)試程序非常麻煩,我們需要這么做
修改了遠(yuǎn)程對(duì)象-》重新編譯安裝程序-》在自己機(jī)器重新安裝服務(wù)-》啟動(dòng)服務(wù)-》查看結(jié)果
其實(shí)可以這么做:
1、修改遠(yuǎn)程對(duì)象中的連接數(shù)據(jù)庫(kù)字符串,由于不是遠(yuǎn)程對(duì)象了,我們必須從本地讀取連接字符串,比如上列我們直接修改為:
SqlConnection conn=new SqlConnection("server=(local);uid=sa;pwd=;database=UBISOFT");
2、修改客戶端代碼,直接實(shí)例化遠(yuǎn)程對(duì)象
????????????RemoteObject.MyObject?app? = ? new ?RemoteObject.MyObject();
等到正式部署的時(shí)候我們還原數(shù)據(jù)庫(kù)連接字符串從config文件中讀取,還原遠(yuǎn)程對(duì)象從遠(yuǎn)程讀取即可。
如果對(duì)windows服務(wù)還不是很清楚,請(qǐng)看以下文章:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/vbwlkwalkthroughcreatingwindowsserviceapplication.asp
http://www.cnblogs.com/lovecherry/archive/2005/03/25/125527.html
首先明確一點(diǎn):iis來(lái)承載的話只能是http通道方式的。
我們來(lái)建立一個(gè)web項(xiàng)目,比如叫remoting,刪除項(xiàng)目中的所有webform,把遠(yuǎn)程對(duì)象dll-RemoteObject.dll復(fù)制到項(xiàng)目的dll文件夾下面,然后打開(kāi)web.config進(jìn)行服務(wù)端設(shè)置:
???? < appSettings >
???????????? < add? key ="strconn" ?value ="server=(local);uid=sa;pwd=;database=UBISOFT" ? />
???? </ appSettings >
???? < system .runtime.remoting >
???????? < application >
???????????? < service >
???????????????? < wellknown? type ="RemoteObject.MyObject,RemoteObject" ?objectUri ="MyObject.soap"
????????????????????mode ="SingleCall" ? />
???????????? </ service > ????
???????????? < channels >
???????????????? < channel? ref ="http" />
???????????? </ channels > ????
???????? </ application >
???? </ system.runtime.remoting >
</ configuration >
來(lái)分析一下這個(gè)config:
1、可能大家還不是很理解type屬性,其實(shí)type屬性分兩部分
<命名空間.類名>,<程序集>
2、objectURi是用來(lái)表示對(duì)象的uri的,到時(shí)候我們用這個(gè)uri來(lái)連接到服務(wù)端
3、我們需要為uri指定soap(soap格式化)或者rem(二進(jìn)制格式化)后綴
要進(jìn)行測(cè)試其實(shí)很簡(jiǎn)單,我們?cè)跒g覽器輸入:http://localhost/remoting/MyObject.soap?wsdl
進(jìn)行測(cè)試,如果發(fā)生問(wèn)題基本就是配置文件的問(wèn)題或者對(duì)象dll沒(méi)有正確復(fù)制到dll目錄
接下來(lái)修改一下客戶端的配置文件就可以了,主要是修改地址。
? < appSettings >
? < add? key ="ServiceURL" ?value ="http://localhost/remoting/MyObject. soap"/>
? </ appSettings >
</ configuration >
iis承載方式默認(rèn)是80端口,我們不需要在端口上做任何設(shè)置。還需要注意到的是iis方式,我們使用這樣的格式作為地址:
http://ip地址/虛擬目錄/遠(yuǎn)程對(duì)象.soap
運(yùn)行了客戶端以后如果我們的數(shù)據(jù)量比較大的話,就算是本機(jī)我們也能感受到延遲,比tcp方式延遲厲害很多很多,其實(shí)http方式的remoting效率比webservice還要差,具體選擇http方式的remoting還是webservice還是要看我們是不是對(duì)對(duì)象的狀態(tài)有需求。
iis的部署也是自動(dòng)啟動(dòng)服務(wù)的,還有一個(gè)優(yōu)點(diǎn)就是可以結(jié)合iis的windows身份認(rèn)證,這個(gè)參照一些iis的配置文章,這里就不說(shuō)了。
下面還是要來(lái)看一下兩種【
通道】
:
??? 默認(rèn)情況下,HTTP 通道使用 SOAP 格式化程序,因此,如果客戶端需要通過(guò) Internet 訪問(wèn)對(duì)象,則可以使用 HTTP 通道。由于這種方法使用 HTTP,所以允許客戶端通過(guò)防火墻遠(yuǎn)程訪問(wèn) .NET 對(duì)象。將這些對(duì)象集成在 IIS 中,即可將其配置為 Web 服務(wù)對(duì)象。隨后,客戶端就可以讀取這些對(duì)象的 WSDL 文件,以便使用 SOAP 與 Remoting 對(duì)象通信。
??? 默認(rèn)情況下,TCP 通道使用二進(jìn)制格式化程序。此格式化程序以二進(jìn)制格式進(jìn)行數(shù)據(jù)的序列化,并使用原始套接字在網(wǎng)絡(luò)中傳送數(shù)據(jù)。如果對(duì)象部署在受防火墻保護(hù)的封閉環(huán)境中,則此方法是理想的選擇。該方法使用套接字在對(duì)象之間傳遞二進(jìn)制數(shù)據(jù),因此性能更好。由于它使用 TCP 通道來(lái)提供對(duì)象,因此具有在封閉環(huán)境中開(kāi)銷較小的優(yōu)點(diǎn)。由于防火墻和配置問(wèn)題,此方法不能在 Internet 上使用。
因此我們也需要更根據(jù)自己的需求來(lái)選擇通道!看看remoting有這么多可以選擇的方式:選擇激活模式,選擇通道,選擇承載方式,如此多的選擇給了我們靈活的同時(shí)也增加了理解remoting的難度。
msdn相關(guān)章節(jié):
http://msdn.microsoft.com/library/CHS/cpguide/html/cpconChannels.asp
最后說(shuō)一下前面的遺留問(wèn)題,為什么會(huì)發(fā)生這個(gè)安全異常?
http://www.cnblogs.com/lovecherry/archive/2005/05/20/159335.html
msdn說(shuō):
依賴于運(yùn)行時(shí)類型驗(yàn)證的遠(yuǎn)程處理系統(tǒng)必須反序列化一個(gè)遠(yuǎn)程流,然后才能開(kāi)始使用它,未經(jīng)授權(quán)的客戶端可能會(huì)試圖利用反序列化這一時(shí)機(jī)。為了免受這種攻擊,.NET 遠(yuǎn)程處理提供了兩個(gè)自動(dòng)反序列化級(jí)別:Low 和 Full。Low(默認(rèn)值)防止反序列化攻擊的方式是,在反序列化時(shí),只處理與最基本的遠(yuǎn)程處理功能關(guān)聯(lián)的類型,如自動(dòng)反序列化遠(yuǎn)程處理基礎(chǔ)結(jié)構(gòu)類型、有限的系統(tǒng)實(shí)現(xiàn)類型集和基本的自定義類型集。
Full 反序列化級(jí)別支持遠(yuǎn)程處理在所有情況下支持的所有自動(dòng)反序列化類
型。
我們首先來(lái)修改服務(wù)端的配置文件:
???? < system .runtime.remoting >
???????? < application? name ="RemoteServer" >
???????????? < service >
???????????????? < wellknown? type ="RemoteObject.MyObject,RemoteObject" ?objectUri ="RemoteObject.MyObject"
????????????????????mode ="Singleton" ? />
???????????? </ service >
???????????? < channels >
???????????????? < channel? ref ="tcp" ?port ="9999" />
???????????????? < serverProviders > ?
???????????????????? < provider? ref ="wsdl" ? />
???????????????????? < formatter? ref ="soap" ?typeFilterLevel ="Full" ? />
???????????????????? < formatter? ref ="binary" ?typeFilterLevel ="Full" ? />
???????????????????? </ serverProviders >
???????????? </ channels >
???????? </ application >
???? </ system.runtime.remoting >
</ configuration >
當(dāng)然也可以用程序進(jìn)行設(shè)置:






????????????BinaryServerFormatterSinkProvider?serverProvider? = ? new ?BinaryServerFormatterSinkProvider();?
????????????BinaryClientFormatterSinkProvider?clientProvider? = ? new ?BinaryClientFormatterSinkProvider();?
????????????serverProvider.TypeFilterLevel? = ?TypeFilterLevel.Full;?
????????????IDictionary?props? = ? new ?Hashtable();?
????????????props[ " port " ]? = ? 9999 ;?
????????????TcpChannel?channel? = ? new ?TcpChannel(props,clientProvider,serverProvider);?
????????????ChannelServices.RegisterChannel(channel);?
????????????Console.ReadLine();
客戶端還要用程序進(jìn)行調(diào)整:
若要使用配置文件設(shè)置反序列化級(jí)別,必須顯式指定 <formatter> 元素的 typeFilterLevel 屬性。雖然這通常是在服務(wù)器端指定的, 但您還必須為注冊(cè)來(lái)偵聽(tīng)回調(diào)的客戶端上的任何信道指定這一屬性 ,以控制其反序列化級(jí)別
在程序前面加上和服務(wù)端基本相同的代碼:
????????????BinaryClientFormatterSinkProvider?clientProvider? = ? new ?BinaryClientFormatterSinkProvider();?
????????????serverProvider.TypeFilterLevel? = ?TypeFilterLevel.Full;?
????????????IDictionary?props? = ? new ?Hashtable();?
????????????props[ " port " ]? = ? 0 ;?
????????????TcpChannel?channel? = ? new ?TcpChannel(props,clientProvider,serverProvider);?
????????????ChannelServices.RegisterChannel(channel);?
這樣就可以了,注意:如果在同一個(gè)機(jī)器上面測(cè)試端口號(hào)應(yīng)設(shè)為不同于服務(wù)器端設(shè)置的端口號(hào),推薦設(shè)置為0(遠(yuǎn)程處理系統(tǒng)自動(dòng)選擇可用端口)
.NET Remoting 自身不提供安全模型。然而,通過(guò)將遠(yuǎn)程對(duì)象駐留在 ASP.NET 中并使用 HTTP 通道進(jìn)行通信,遠(yuǎn)程對(duì)象可以使用 IIS 和 ASP.NET 提供的基本安全服務(wù)。比較而言,TCP 通道和自定義的主機(jī)可執(zhí)行文件能夠提供更高的性能,但這種組合不提供內(nèi)置的安全功能。
? 若要對(duì)客戶端進(jìn)行身份驗(yàn)證,請(qǐng)使用 HTTP 通道,在 ASP.NET 中駐留對(duì)象,以及在 IIS 中禁用匿名訪問(wèn)。
?
? 如果您不擔(dān)心客戶端身份驗(yàn)證問(wèn)題,請(qǐng)使用 TCP 通道,它可以提供更高的性能。
?
? 如果您使用 TCP 通道,請(qǐng)使用 IPSec 保護(hù)客戶端和服務(wù)器之間的通信通道。使用 SSL 來(lái)保護(hù) HTTP 通道。
?
? 如果您需要對(duì)遠(yuǎn)程資源進(jìn)行受信任的調(diào)用,請(qǐng)將組件駐留在 Windows 服務(wù)中,而不是駐留在控制臺(tái)應(yīng)用程序中。
?
? 始終不要向 Internet 公開(kāi)遠(yuǎn)程對(duì)象。在這種情況下,請(qǐng)使用 Web 服務(wù)。
應(yīng)該僅在 Intranet 中使用 .NET Remoting。應(yīng)該使用內(nèi)部方式從 Web 應(yīng)用程序訪問(wèn)對(duì)象。即使對(duì)象駐留在 ASP.NET 中,也不要向 Internet 客戶端公開(kāi)它們,因?yàn)榭蛻舳吮仨毷?.NET 客戶端。
最后,讓我們來(lái)看一篇msdn有關(guān)remoting安全的文章:
http://www.microsoft.com/china/msdn/library/architecture/architecture/architecturetopic/BuildSucApp/BSAAsecmod11.mspx
?
TrackBack:http://www.cnblogs.com/lovecherry/archive/2005/05/20/159598.html
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
