标签:style blog http color io os 使用 ar for
上一篇博文分享了消息队列(MSMQ)技术来实现分布式应用,在这篇博文继续分享下.NET平台下另一种分布式技术——.NET Remoting。
.NET REmoting与MSMQ不同,它不支持离线可得,另外只适合.NET平台的程序进行通信。它提供了一种允许对象通过应用程序域与另一个对象进行交互的框架。.NET 应用程序都在一个主应用程序域中执行的,在一个应用程序域中的代码不能访问另一个应用程序域的数据,然而在某些情况下,我们需要跨应用程序域,与另外的应用程序域进行通信,这时候就可以采用.NET Remoting技术来实现与另一个程序域中的对象进行交互。
.NET Remoting技术是通过通道来实现两个应用程序之间对象的通信的。首先,客户端通过Remoting技术,访问通道来获得服务器端对象,再通过代理解析为客户端对象,也称作透明代理,此时获得客户端对象只是服务器对象的一个引用。这既保证了客户端和服务端有关对象的松散耦合,同时优化了通信的性能。在这个过程中,当客户端通过透明代理来调用远程对象的方法时,此时会将调用封装到一个消息对象中,该消息对象包括远程对象信息,被调用的方法名和参数,然后透明代理会将调用委托给真实代理(RealProxy对象)的Invoke方法来生成一个IMethodCallMessage,接着通过序列化把这个消息对象序列化成数据流发送到通道,通道会把数据流传送到服务器端。当服务器接收到经过格式化的数据之后,首先从中通过反序列化来还原消息对象,之后在服务器端来激活远程对象,并调用对应的方法,而方法的返回结果过程则是按照之前的方法反向重复一遍,具体的实现原理图如下所示:
上面简单介绍了下.NET Remoting实现分布式应用程序的基本原理,这里介绍下在.NET Remoting中涉及的几个重要概念。
SingleTon模式:此为有状态模式。如果设置为SingleTon激活模式,则.NET Remoting将为所有客户端建立同一个对象实例。当对象处于活动状态时,SingleTon实例会处理所有后来的客户端访问请求,而不管它们是同一个客户端,还是其他客户端。SingleTon实例将在方法调用中一直维护其状态,类似static成员的概念
SingleCall模式:是一种无状态模式。一旦设置为SingleCall模式,则当客户端调用远程对象的方法时,Remoting会为每一个客户端建立一个远程对象实例,对象实例的销毁则是由GC自动管理。类似实例成员的概念。
3. 通道:在.NET Remoting中时通过通道来实现两个应用程序域之间对象的通信。.NET Remoting中包括4中通道类型:
前面详细介绍了.NET Remoting相关内容,下面具体看看如何使用.NET Remoting技术来开发分布式应用程序。开发.NET Remoting应用分三步走。
第一步:创建远程对象,该对象必须继承MarshalByRefObject对象。具体的示例代码如下:
1 namespace RemotingObject 2 { 3 // 第一步:创建远程对象 4 // 创建远程对象——必须继承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中不同的通道方式的效果。
第二步:创建服务器端,需要添加System.Runtime.Remoting.dll引用,具体实现代码如下所示:
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 // 第二步:创建宿主应用程序 11 class Server 12 { 13 static void Main(string[] args) 14 { 15 // 1.创建三种通道 16 17 // 创建Tcp通道,端口号9001 18 TcpChannel tcpChannel = new TcpChannel(9001); 19 20 // 创建Http通道,端口号9002 21 HttpChannel httpChannel = new HttpChannel(9002); 22 23 // 创建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通道的优先级 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 }
第三步:创建客户端程序,具体的实现代码如下所示:
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服务器失败"); 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服务器失败"); 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服务器失败"); 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 }
经过上面的三步,我们就完成了这个分布式应用的开发工作,下面测试下该程序是否可以正常运行,首先,运行服务器端,你将看到如下界面:
在.NET Remoting中,是允许同时创建多个通道的,但是.NET Remoting要求通道的名字必须不同,因为名字是用来标识通道的唯一标识符。但上面代码中,我们并没有指明通道的名字,为什么还可以允许成功呢?从上面图片可知,当我们创建通道时,如果没有为其显式指定通道名,则会使用对应的通道类型作为该通道名,如TcpChannel将会以tcp作为通道名,如果想注册多个Tcp通道则必须显式指定其名字。
下面看看运行客户端所获得的结果,具体客户端运行效果如下图所示:
在第三部分中,我们是把服务器的各种通道方式和地址写死在程序中的,这样的实现方式部署起来不方便,下面使用配置文件的方式来配置服务器端的通道类型和服务器地址。 远程对象的定义不需要改变,下面直接看服务器端使用配置文件后的实现代码如下所示:
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 // 打印通道的优先级 18 Console.WriteLine("The priority of the Channel is {0}", channel.ChannelPriority); 19 } 20 Console.WriteLine("按任意键退出……"); 21 Console.ReadLine(); 22 } 23 } 24 }
服务端的配置文件的内容为:
1 <?xml version="1.0" encoding="utf-8" ?> 2 <!--服务端App.config的内容--> 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>
此时,客户端程序的实现代码如下所示:
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("连接服务器失败"); 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>
使用配置文件修改后的分布式程序的运行结果与前面的运行结果一样,这里就不一一贴图了。
到这里,.NET Remoting技术的分享就结束了,本文只是对.NET Remoting技术做了一个基本的介绍,如果想深入了解.NET Remoting技术的话,推荐大家可以看看下面的专题细细品味C#——.Net Remoting专题。在下一篇文章中,继续为大家分享另一种分布式技术——Web Service。
本文的示例代码文件下载:.NETRemotingSample
跟我一起学WCF(2)——利用.NET Remoting技术开发分布式应用
标签:style blog http color io os 使用 ar for
原文地址:http://www.cnblogs.com/zhili/p/NETRemoting.html