日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

跟我一起学WCF(2)——利用.NET Remoting技术开发分布式应用

發(fā)布時間:2023/12/9 asp.net 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 跟我一起学WCF(2)——利用.NET Remoting技术开发分布式应用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、引言

?  上一篇博文分享了消息隊列(MSMQ)技術(shù)來實現(xiàn)分布式應(yīng)用,在這篇博文繼續(xù)分享下.NET平臺下另一種分布式技術(shù)——.NET Remoting。

二、.NET Remoting 介紹

2.1 .NET Remoting簡介

?  .NET REmoting與MSMQ不同,它不支持離線可得,另外只適合.NET平臺的程序進行通信。它提供了一種允許對象通過應(yīng)用程序域與另一個對象進行交互的框架。.NET 應(yīng)用程序都在一個主應(yīng)用程序域中執(zhí)行的,在一個應(yīng)用程序域中的代碼不能訪問另一個應(yīng)用程序域的數(shù)據(jù),然而在某些情況下,我們需要跨應(yīng)用程序域,與另外的應(yīng)用程序域進行通信,這時候就可以采用.NET Remoting技術(shù)來實現(xiàn)與另一個程序域中的對象進行交互。

2.2 .NET Remoting基本原理

?  .NET Remoting技術(shù)是通過通道來實現(xiàn)兩個應(yīng)用程序之間對象的通信的。首先,客戶端通過Remoting技術(shù),訪問通道來獲得服務(wù)器端對象,再通過代理解析為客戶端對象,也稱作透明代理,此時獲得客戶端對象只是服務(wù)器對象的一個引用。這既保證了客戶端和服務(wù)端有關(guān)對象的松散耦合,同時優(yōu)化了通信的性能。在這個過程中,當客戶端通過透明代理來調(diào)用遠程對象的方法時,此時會將調(diào)用封裝到一個消息對象中,該消息對象包括遠程對象信息,被調(diào)用的方法名和參數(shù),然后透明代理會將調(diào)用委托給真實代理(RealProxy對象)的Invoke方法來生成一個IMethodCallMessage,接著通過序列化把這個消息對象序列化成數(shù)據(jù)流發(fā)送到通道,通道會把數(shù)據(jù)流傳送到服務(wù)器端。當服務(wù)器接收到經(jīng)過格式化的數(shù)據(jù)之后,首先從中通過反序列化來還原消息對象,之后在服務(wù)器端來激活遠程對象,并調(diào)用對應(yīng)的方法,而方法的返回結(jié)果過程則是按照之前的方法反向重復(fù)一遍,具體的實現(xiàn)原理圖如下所示:

2.3 .NET Remoting幾個重要概念

?  上面簡單介紹了下.NET Remoting實現(xiàn)分布式應(yīng)用程序的基本原理,這里介紹下在.NET Remoting中涉及的幾個重要概念。

  • 遠程對象:是運行在服務(wù)器端的對象,客戶端不能直接調(diào)用,由于.NET Remoting傳遞的對象是以引用的方式,因此所傳遞的遠程對象必須繼承MarshalByRefObject類,這個類可以使遠程對象在.NET Remoting應(yīng)用通信中使用,支持對象的跨域邊界訪問。
  • 遠程對象的激活方式:在訪問服務(wù)器端的一個對象實例之前,必須通過一個名為Activation的進程創(chuàng)建它并進行初始化。這種客戶端通過通道來創(chuàng)建遠程對象的方式稱為對象的激活。在.NET Remoting中,遠程對象的激活分為兩大類:服務(wù)器端激活和客戶端激活。
    • 服務(wù)器端激活,又叫做WellKnow(知名對象)激活模式,為什么稱為知名對象激活模式呢?是因為服務(wù)應(yīng)用程序在激活對象實例之前會在一個眾所周知的統(tǒng)一資源標示符(URI)上發(fā)布這個類型,然后該服務(wù)器進行會為此類型配置一個WellKnow對象,并根據(jù)指定的端口或地址來發(fā)布對象。.NET Remoting把服務(wù)器端激活又分為SingleTon模式和SingleCall模式兩種。

      SingleTon模式:此為有狀態(tài)模式。如果設(shè)置為SingleTon激活模式,則.NET Remoting將為所有客戶端建立同一個對象實例。當對象處于活動狀態(tài)時,SingleTon實例會處理所有后來的客戶端訪問請求,而不管它們是同一個客戶端,還是其他客戶端。SingleTon實例將在方法調(diào)用中一直維護其狀態(tài),類似static成員的概念

      SingleCall模式:是一種無狀態(tài)模式。一旦設(shè)置為SingleCall模式,則當客戶端調(diào)用遠程對象的方法時,Remoting會為每一個客戶端建立一個遠程對象實例,對象實例的銷毀則是由GC自動管理。類似實例成員的概念。

    • 客戶端激活:與Wellknow模式不同,。NET Remoting在激活每個對象實例的時候,會給每個客戶端激活的類型指派一個URI。客戶端激活模式一旦獲得客戶端的請求,將為每一個客戶端都建立一個實例引用。SingleCall模式與客戶端激活模式的區(qū)別有:首先,對象實例創(chuàng)建的時間不同。客戶端激活方式是客戶一旦發(fā)出調(diào)用請求就實例化,而SingleCall則要等到調(diào)用對象方法時再創(chuàng)建。其次,SingleCall模式激活的對象是無狀態(tài)的,對象聲明周期由GC管理,而客戶端激活的對象是有狀態(tài)的,其生命周期可自定義。第三,兩種激活模式在服務(wù)器端和客戶端實現(xiàn)的方法不一樣,尤其是在客戶端,SingleCall模式由GetObject()來激活,它調(diào)用對象默認的構(gòu)造函數(shù),而客戶端激活模式,則通過CreateInstance()來激活,它可以傳遞參數(shù),所以可以調(diào)用自定義的構(gòu)造函數(shù)來創(chuàng)建實例。

      3. 通道:在.NET Remoting中時通過通道來實現(xiàn)兩個應(yīng)用程序域之間對象的通信。.NET Remoting中包括4中通道類型:

  • TcpChannel:Tcp通道使用Tcp協(xié)議來跨越.Net Remoting邊界來傳輸序列化的消息流,TcpChannel默認使用二進制格式序列化消息對象,因此具有更高的傳輸性能,但不提供任何內(nèi)置的安全功能。
  • HttpChannel:Http通道使用Http協(xié)議在客戶端和服務(wù)器之間發(fā)生消息,使其在Internet上穿越防火墻來傳輸序列化的消息流(這里準確講不能說穿越,主要是因為防火墻都開放了80端口,所以使用Http協(xié)議可以穿過防火墻進行數(shù)據(jù)的傳輸,如果防火墻限制了80端口,Http協(xié)議也照樣不能穿越防火墻)。默認情況下,HttpChannel使用Soap格式序列化消息對象,因此它具有更好的互操作性,并且可以使用Http協(xié)議中的加密機制來對消息進行加密來保證安全性。因此,通常在局域網(wǎng)內(nèi),我們更多地使用TcpChannel,如果要穿越防火墻,則使用HttpChannel。
  • IpcChannel:進程間通信,只使用同一個系統(tǒng)進程之間的通信,不需要主機名和端口號。而使用Http通道和Tcp通道都要指定主機名和端口號。
  • 自定義通道:自定義的傳輸通道可以使用任何基本的傳輸協(xié)議來進行通信,如UDP協(xié)議、SMTP協(xié)議等。
  • 三、利用.NET Remoting技術(shù)開發(fā)分布式應(yīng)用三部曲

    ?  前面詳細介紹了.NET Remoting相關(guān)內(nèi)容,下面具體看看如何使用.NET Remoting技術(shù)來開發(fā)分布式應(yīng)用程序。開發(fā).NET Remoting應(yīng)用分三步走。

    第一步:創(chuàng)建遠程對象,該對象必須繼承MarshalByRefObject對象。具體的示例代碼如下:

    1 namespace RemotingObject 2 { 3 // 第一步:創(chuàng)建遠程對象 4 // 創(chuàng)建遠程對象——必須繼承MarshalByRefObject,該類支持對象的跨域邊界訪問 5 public class MyRemotingObject :MarshalByRefObject 6 { 7 // 用來測試Tcp通道 8 public int AddForTcpTest(int a, int b) 9 { 10 return a + b; 11 } 12 13 // 用來測試Http通道 14 public int MinusForHttpTest(int a, int b) 15 { 16 return a - b; 17 } 18 19 // 用來測試IPC通道 20 public int MultipleForIPCTest(int a, int b) 21 { 22 return a * b; 23 } 24 } 25 }

      遠程對象分別定義3個方法,目的是為了測試3中不同的通道方式的效果。

    第二步:創(chuàng)建服務(wù)器端,需要添加System.Runtime.Remoting.dll引用,具體實現(xiàn)代碼如下所示:

    1 using System; 2 using System.Runtime.Remoting; 3 using System.Runtime.Remoting.Channels; 4 using System.Runtime.Remoting.Channels.Http; 5 using System.Runtime.Remoting.Channels.Ipc; 6 using System.Runtime.Remoting.Channels.Tcp; 7 8 namespace RemotingServerHost 9 { 10 // 第二步:創(chuàng)建宿主應(yīng)用程序 11 class Server 12 { 13 static void Main(string[] args) 14 { 15 // 1.創(chuàng)建三種通道 16 17 // 創(chuàng)建Tcp通道,端口號9001 18 TcpChannel tcpChannel = new TcpChannel(9001); 19 20 // 創(chuàng)建Http通道,端口號9002 21 HttpChannel httpChannel = new HttpChannel(9002); 22 23 // 創(chuàng)建IPC通道,端口號9003 24 IpcChannel ipcChannel = new IpcChannel("IpcTest"); 25 26 // 2.注冊通道 27 ChannelServices.RegisterChannel(tcpChannel, false); 28 ChannelServices.RegisterChannel(httpChannel, false); 29 ChannelServices.RegisterChannel(ipcChannel, false); 30 31 // 打印通道信息 32 // 打印Tcp通道的名稱 33 Console.WriteLine("The name of the TcpChannel is {0}", tcpChannel.ChannelName); 34 // 打印Tcp通道的優(yōu)先級 35 Console.WriteLine("The priority of the TcpChannel is {0}", tcpChannel.ChannelPriority); 36 37 Console.WriteLine("The name of the HttpChannel is {0}", httpChannel.ChannelName); 38 Console.WriteLine("The priority of the httpChannel is {0}", httpChannel.ChannelPriority); 39 40 Console.WriteLine("The name of the IpcChannel is {0}", ipcChannel.ChannelName); 41 Console.WriteLine("The priority of the IpcChannel is {0}", ipcChannel.ChannelPriority); 42 43 // 3. 注冊對象 44 // 注冊MyRemotingObject到.NET Remoting運行庫中 45 RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotingObject.MyRemotingObject), "MyRemotingObject", WellKnownObjectMode.Singleton); 46 Console.WriteLine("Press any key to exit"); 47 Console.ReadLine(); 48 } 49 } 50 }

    第三步:創(chuàng)建客戶端程序,具體的實現(xiàn)代碼如下所示:

    1 using RemotingObject; 2 using System; 3 4 namespace RemotingClient 5 { 6 class Client 7 { 8 static void Main(string[] args) 9 { 10 // 使用Tcp通道得到遠程對象 11 //TcpChannel tcpChannel = new TcpChannel(); 12 //ChannelServices.RegisterChannel(tcpChannel, false); 13 MyRemotingObject proxyobj1 = Activator.GetObject(typeof(MyRemotingObject), "tcp://localhost:9001/MyRemotingObject") as MyRemotingObject; 14 if (proxyobj1 == null) 15 { 16 Console.WriteLine("連接TCP服務(wù)器失敗"); 17 } 18 19 //HttpChannel httpChannel = new HttpChannel(); 20 //ChannelServices.RegisterChannel(httpChannel, false); 21 MyRemotingObject proxyobj2 = Activator.GetObject(typeof(MyRemotingObject), "http://localhost:9002/MyRemotingObject") as MyRemotingObject; 22 if (proxyobj2 == null) 23 { 24 Console.WriteLine("連接Http服務(wù)器失敗"); 25 } 26 27 //IpcChannel ipcChannel = new IpcChannel(); 28 //ChannelServices.RegisterChannel(ipcChannel, false); 29 MyRemotingObject proxyobj3 = Activator.GetObject(typeof(MyRemotingObject), "ipc://IpcTest/MyRemotingObject") as MyRemotingObject; 30 if (proxyobj3 == null) 31 { 32 Console.WriteLine("連接Ipc服務(wù)器失敗"); 33 } 34 // 輸出信息 35 Console.WriteLine("This call object by TcpChannel, 100 + 200 = {0}", proxyobj1.AddForTcpTest(100, 200)); 36 Console.WriteLine("This call object by HttpChannel, 100 - 200 = {0}", proxyobj2.MinusForHttpTest(100, 200)); 37 Console.WriteLine("This call object by IpcChannel, 100 * 200 = {0}", proxyobj1.MultipleForIPCTest(100, 200)); 38 Console.WriteLine("Press any key to exit!"); 39 Console.ReadLine(); 40 } 41 } 42 }

      經(jīng)過上面的三步,我們就完成了這個分布式應(yīng)用的開發(fā)工作,下面測試下該程序是否可以正常運行,首先,運行服務(wù)器端,你將看到如下界面:

      在.NET Remoting中,是允許同時創(chuàng)建多個通道的,但是.NET Remoting要求通道的名字必須不同,因為名字是用來標識通道的唯一標識符。但上面代碼中,我們并沒有指明通道的名字,為什么還可以允許成功呢?從上面圖片可知,當我們創(chuàng)建通道時,如果沒有為其顯式指定通道名,則會使用對應(yīng)的通道類型作為該通道名,如TcpChannel將會以tcp作為通道名,如果想注冊多個Tcp通道則必須顯式指定其名字。

      下面看看運行客戶端所獲得的結(jié)果,具體客戶端運行效果如下圖所示:

    ?四、使用配置文件來重寫上面的分布式程序

      在第三部分中,我們是把服務(wù)器的各種通道方式和地址寫死在程序中的,這樣的實現(xiàn)方式部署起來不方便,下面使用配置文件的方式來配置服務(wù)器端的通道類型和服務(wù)器地址。  遠程對象的定義不需要改變,下面直接看服務(wù)器端使用配置文件后的實現(xiàn)代碼如下所示:

    1 using System; 2 using System.Runtime.Remoting; 3 using System.Runtime.Remoting.Channels; 4 5 namespace RemotingServerHostByConfig 6 { 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 RemotingConfiguration.Configure("RemotingServerHostByConfig.exe.config", false); 12 13 foreach (var channel in ChannelServices.RegisteredChannels) 14 { 15 // 打印通道的名稱 16 Console.WriteLine("The name of the Channel is {0}", channel.ChannelName); 17 // 打印通道的優(yōu)先級 18 Console.WriteLine("The priority of the Channel is {0}", channel.ChannelPriority); 19 } 20 Console.WriteLine("按任意鍵退出……"); 21 Console.ReadLine(); 22 } 23 } 24 }

      服務(wù)端的配置文件的內(nèi)容為:

    1 <?xml version="1.0" encoding="utf-8" ?> 2 <!--服務(wù)端App.config的內(nèi)容--> 3 <configuration> 4 <startup> 5 <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> 6 </startup> 7 <system.runtime.remoting> 8 <application> 9 <service> 10 <wellknown mode="Singleton" 11 type="RemotingObject.MyRemotingObject,RemotingObject" 12 objectUri="MyRemotingObject"/> 13 </service> 14 <channels> 15 <channel port="9001" ref="tcp"/> 16 <channel port="9002" ref="http"/> 17 <channel portName="IpcTest" ref="ipc"/> <!--Ipc通道不需要端口號--> 18 </channels> 19 </application> 20 </system.runtime.remoting> 21 </configuration>

      此時,客戶端程序的實現(xiàn)代碼如下所示:

    1 using RemotingObject; 2 using System; 3 using System.Runtime.Remoting; 4 5 namespace RemotingClientByConfig 6 { 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 //使用HTTP通道得到遠程對象 12 RemotingConfiguration.Configure("RemotingClientByConfig.exe.config", false); 13 MyRemotingObject proxyobj1 = new MyRemotingObject(); 14 if (proxyobj1 == null) 15 { 16 Console.WriteLine("連接服務(wù)器失敗"); 17 } 18 19 Console.WriteLine("This call object by TcpChannel, 100 + 200 = {0}", proxyobj1.AddForTcpTest(100, 200)); 20 Console.WriteLine("This call object by HttpChannel, 100 - 200 = {0}", proxyobj1.MinusForHttpTest(100, 200)); 21 Console.WriteLine("This call object by IpcChannel, 100 * 200 = {0}", proxyobj1.MultipleForIPCTest(100, 200)); 22 Console.WriteLine("Press any key to exit!"); 23 Console.ReadLine(); 24 } 25 } 26 }

      客戶端配置文件為:

    1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <startup> 4 <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> 5 </startup> 6 <system.runtime.remoting> 7 <application> 8 <client> 9 <wellknown type="RemotingObject.MyRemotingObject,RemotingObject" 10 url="http://localhost:9002/MyRemotingObject" /> 11 </client> 12 <channels> 13 <channel ref="tcp" port="0"></channel> 14 <channel ref="http" port="0"></channel> 15 <channel ref="ipc" port="0"></channel> 16 </channels> 17 </application> 18 </system.runtime.remoting> 19 </configuration>

      使用配置文件修改后的分布式程序的運行結(jié)果與前面的運行結(jié)果一樣,這里就不一一貼圖了。

    五、總結(jié)

    ?  到這里,.NET Remoting技術(shù)的分享就結(jié)束了,本文只是對.NET Remoting技術(shù)做了一個基本的介紹,如果想深入了解.NET Remoting技術(shù)的話,推薦大家可以看看下面的專題細細品味C#——.Net Remoting專題。在下一篇文章中,繼續(xù)為大家分享另一種分布式技術(shù)——Web Service。

      ?本文的示例代碼文件下載:.NETRemotingSample

    ?

    總結(jié)

    以上是生活随笔為你收集整理的跟我一起学WCF(2)——利用.NET Remoting技术开发分布式应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。