WCF分布式开发必备知识(2):.Net Remoting

简介:
     上一节我们学习了网络分布式编程中的MSMQ消息队列技术.本节我们将学习分布式编程的另外一个重要的技术. Net Remoting,文章的结构还是先讨论基本概念,再来探讨具体的技术实现,希望能和大家一起交流学习.
      . Net Remoting技术 ,我们可以将其看作是一种分布式处理方式。作为应用程序之间通信的一种机制,.Net Remoting与MSMQ消息队列不同,它不支持离线脱机消息,另外只适合.Net平台间程序的通信.从微软的产品角度来看,可以说Remoting就是分布式组件DCOM的一种升级,它改善了很多功能,并极好的融合到.Net平台下。.NET Remoting 提供了一种允许对象通过应用程序域与另一对象进行交互的框架。这也正是我们使用Remoting的原因。为什么呢?在Windows操作系统中,是将应用程序分离为单独的进程。这个进程形成了应用程序代码和数据周围的一道边界。如果不采用进程间通信IPC(Internet Process Connection)机制,则在一个进程中执行的代码就不能访问另一进程。这是一种操作系统对应用程序的保护机制。然而在某些情况下,我们需要跨过应用程序域,与另外的应用程序域进行通信,即穿越边界(参考MSDN)。
    .Net Remoting的通信架构如下图.
 我们可以通过上图简单理解一下.Net Remoting的通信框架,而现在来介绍一下其中涉及到的几个比较重要的概念:
     1.通道(channel),
  在.Net Remoting中是通过通道(channel)来实现两个应用程序域之间对象的通信的。首先,客户端通过Remoting,访问通道以获得服务端对象,再通过代理解析为客户端对象。这就提供一种可能性,即以服务的方式来发布服务器对象。远程对象代码可以运行在服务器上(如服务器激活的对象和客户端激活的对象),然后客户端再通过Remoting连接服务器,获得该服务对象并通过序列化在客户端运行。
     通道(channel)有4种严格说,很多资料上说有2-3种.应该有4种.HttpChanel和TcpChanel.
    (1)HttpChannel。在将远程对象驻留在 ASP.NET 中时,可以使用此通道。此通道使用 HTTP 协议在客户端和服务器之间发送消息。可以使用HTTP协议中的加密机制.需要主机名字和端口号.
(2)TcpChannel。在将远程对象驻留在  操作系统服务或其他可执行文件中时,此通道使用 TCP 套接字在客户端和服务器之间发送消息。同样需要提供主机名字和端口号.不提供任何内置的安全功能。
    (3)IPCChanel,进程间通道,只使用同一个系统内,进程之见的通信.不需要需要主机名字和端口号.
(4)自定义通道 。自定义的传输通道可以使用任何基本的传输协议UDP\SMTP\IPX\消息排队等机制进行通信.用户可以根据需要自定义方式协议,因此.Net Remoting相对其他机制更加的灵活。不提供任何内置的安全功能。
     2.远程对象(Obeject)
  在Remoting中要传递的对象,设计者除了需要了解通道的类型和端口号之外,无需再了解数据包的格式。但必须注意的是,客户端在获取服务器端对象时,并不是获得实际的服务端对象,而是通过代理获得它的引用。远程对象要继承自MarshalByRefObject类,这个可以使远程对象在remoting应用通信中使用,支持对象的跨域边界访问.
     3.激活方式
       (1)服务器端激活,又叫做知名WellKnown方式,是因为服务器应用程序在激活对象实例之前会在一个众所周知的统一资源标识符(URI)上来发布这个类型。然后该服务器进程会为此类型配置一个WellKnown对象,并根据指定的端口或地址来发布对象。服务器端激活又分为SingleTon模式和SingleCall模式两种。SingleTon模式:此为有状态模式。如果设置为SingleTon激活方式,则Remoting将为所有客户端建立同一个对象实例。SingleCall模式:SingleCall是一种无状态模式。一旦设置为SingleCall模式,则当客户端调用远程对象的方法时, Remoting会为每一个客户端建立一个远程对象实例,至于对象实例的销毁则是由GC自动管理的。
  (2)客户端激活。与WellKnown模式不同, Remoting在激活每个对象实例的时候,会给每个客户端激活的类型指派一个URI。客户端激活模式一旦获得客户端的请求,将为每一个客户端都建立一个实例引用。SingleCall模式和客户端激活模式是有区别的:首先,对象实例创建的时间不一样。客户端激活方式是客户一旦发出调用的请求,就实例化;而SingleCall则是要等到调用对象方法时再创建。其次,SingleCall模式激活的对象是无状态的,对象生命期的管理是由GC管理的,而客户端激活的对象则有状态,其生命周期可自定义。其三,两种激活模式在服务器端和客户端实现的方法不一样。尤其是在客户端,SingleCall模式是由 GetObject()来激活,它调用对象默认的构造函数。而客户端激活模式,则通过CreateInstance()来激活,它可以传递参数,所以可以调用自定义的构造函数来创建实例。(详细参考MSDN)
     (4)代理Proxy,客户端访问的不能直接访问远程对象,它是通过代理来访问代理上的方法.代理对象又分为透明代理和真实代理,区别是,在透明代理上,客户通过Invoke调用的是远程对象上真实代理的方法.然后把消息再传递给通道.
     好了,介绍到此我们也基本了解.Net Remoting相关的知识,下面我们来学习的是具体的编程实现部分.程序大体分为3个部分远程对象\服务器\可户端.现在我们来分别实现.服务器端要添加引用System.Runtime.Remoting的程序集.
    1.远程对象(RemoteOject),也就是我们远程要访问的对象.首先定义一个Class,继承MarshalByRefObject,可以使用在remoting应用中,支持对象的跨域边界访问.具体代码如下:
InBlock.gif 1namespace RemoteObject 
InBlock.gif 2{ 
InBlock.gif 3         //创建远程对象.继承MarshalByRefObject,可以使用在remoting应用中,支持对象的跨域边界访问 
InBlock.gif 4         public  class MyRemoteObject : MarshalByRefObject //访问远程对象需要通过代理 
InBlock.gif 5        { 
InBlock.gif 6                 //简单的例子,实现加法功能的方法AddForTcpTest,这个远程对象可以实现封装业务逻辑或者数据访问等操作。 
InBlock.gif 7                 // 
InBlock.gif 8                 public  int AddForTcpTest( int a,  int b) 
InBlock.gif 9                { 
InBlock.gif10                         return a + b; 
InBlock.gif11                } 
InBlock.gif12                 //实现减法功能的方法MinusForHttpTest,测试HTTP通道。 
InBlock.gif13                 public  int MinusForHttpTest( int a,  int b) 
InBlock.gif14                { 
InBlock.gif15                         return a - b; 
InBlock.gif16                } 
InBlock.gif17                 //实现乘法功能的方法MultipleForIpcTest,测试Ipc通道 
InBlock.gif18                 public  int MultipleForIpcTest( int a,  int b) 
InBlock.gif19                { 
InBlock.gif20                         return a * b; 
InBlock.gif21                } 
InBlock.gif22        }    
InBlock.gif23 
InBlock.gif24}
     对象分别定义了3种方法,目的是为了测试3种不同的通道方式的效果. //简单的例子,实现加法功能的方法AddForTcpTest,这个远程对象可以实现封装业务逻辑或者数据访问等操作。实现减法功能的方法MinusForHttpTest,测试HTTP通道。实现乘法功能的方法MultipleForIpcTest,测试Ipc通道.
     2服务器端,注册通道,以便进程间通信,我们这里注册了三种通道,分别是HttpChanel\TcpChanel\IPCChanel.具体代码如下:
//////////////////////////////////// //创建三种通道 //////////////////////////////////////////////// /
            
/// 创建Tcp通道,使用端口10001
            TcpChannel chanTcp  =   new  TcpChannel( 10001 );
            
/// 创建Http通道,使用端口10002
            HttpChannel chanHttp  =   new  HttpChannel( 10002 );
            
/// 创建IPC通道,使用端口10003,IPC只适合同系统内进程的通信,所以不需要设置端口和主机名
            IpcChannel chanIPC  =   new  IpcChannel( " FrankTestIpc " );
            
//////////////////////////////////// //注册通道 //////////////////////////////////////////////// //

            
/// 注册TCP通道
            ChannelServices.RegisterChannel(chanTcp);
            
/// 注册HTTP通道
            ChannelServices.RegisterChannel(chanHttp);
            
/// 注册IPC通道
            ChannelServices.RegisterChannel(chanIPC);

            
/////////////////////////////////////// /打印通道 //////////////////////////////////////////////// /
             //  打印TCP通道的名称.
            Console.WriteLine( " The name of the TCPChannel is {0}. " ,
                chanTcp.ChannelName);
            
//  打印TCP通道的优先级.
            Console.WriteLine( " The priority of the TCPChannel is {0}. " ,
                chanTcp.ChannelPriority);

            
//  打印Http通道的名称.
            Console.WriteLine( " The name of the HttpChannel is {0}. " ,
                chanHttp.ChannelName);
            
//  打印Http通道的优先级.
            Console.WriteLine( " The priority of the HttpChannel is {0}. " ,
                chanHttp.ChannelPriority);

            
//  打印IPC通道的名称.
            Console.WriteLine( " The name of the IpcChannel is {0}. " ,
                chanIPC.ChannelName);
            
//  打印IPC通道的优先级.
            Console.WriteLine( " The priority of the IpcChannel is {0}. " ,
                chanIPC.ChannelPriority);
            
////////////////////////////////////////// /注册对象 //////////////////////////////////////////////// /
             // 注册对象MyRemoteObject到Net Remoting运行库
            
// 配置远程通信基础框架.第2个参数是对象的URI,“RemoteObject.MyRemoteObject”,客户端URL一定要和这个匹配,不然会出现查找不到代理对象的异常
            RemotingConfiguration.RegisterWellKnownServiceType( typeof (RemoteObject.MyRemoteObject),  " RemoteObject.MyRemoteObject " , WellKnownObjectMode.Singleton);
            
// 远程对象激活方式是单件激活模式,每次调用共享一个对象,SingleCall激活模式会在每次调用的时候产生一个新对象

            
// 向信道暴露一个IPC远程对象.
            
// RemotingConfiguration.RegisterWellKnownService(Type(typeof(RemoteObject), "RemoteObject.rem", System.Runtime.Remoting.WellKnownObjectMode.Singleton);

            
////////////////// /For Debug //////////////////////////////////////////////////////////////////////// /
            Console.WriteLine( " Press any key to exit! " );
            System.Console.ReadLine();
            创建Tcp通道,使用端口10001, 创建Http通道,使用端口10002,创建IPC通道,使用端口10003,IPC只适合同系统内进程的通信,所以不需要设置端口和主机名.然后调用ChannelServices类的静态方法RegisterChannel进行注册.最后一步注册对象MyRemoteObject到Net Remoting运行库,同时要先配置远程通信基础框架.第2个参数是对象的URI,“RemoteObject.MyRemoteObject”,客户端URL一定要和这个匹配,不然会出现查找不到代理对象的异常.WellKnownObjectMode.Singleton);远程对象激活方式是单件激活模式,每次调用共享一个对象,SingleCall激活模式会在每次调用的时候产生一个新对象.
     3客户端是控制台程序(实际项目类型可以替换,这里只是为了作为例子选择控制台类型).配置文件进行的设置如下:
InBlock.gif 1<configuration> 
InBlock.gif 2        <appSettings> 
InBlock.gif 3                <add key= "ServiceURLTcp" value= "tcp://localhost:10001/RemoteObject.MyRemoteObject"/> 
InBlock.gif 4                <add key="ServiceURLHttp" value="http://localhost:10002/RemoteObject.MyRemoteObject"/> 
InBlock.gif 5                <add key="ServiceURLIpc" value="ipc://FrankTestIpc/RemoteObject.MyRemoteObject"/> 
InBlock.gif 6        </appSettings> 
InBlock.gif 7        <system.runtime.remoting> 
InBlock.gif 8                        
InBlock.gif 9             </system.runtime.remoting> 
InBlock.gif10</configuration>
     配置文件设置的是具体通道的URL信息.具体c#实现代码如下:
InBlock.gif
InBlock.gif 2namespace RemoteClient 
InBlock.gif 3{ 
InBlock.gif 4         class MyClient //客户端 
InBlock.gif 5        { 
InBlock.gif 6                [STAThread] //主线程,建立客户端程序:注册通道,根据URL得到对象代理,使用代理调用远程对象
InBlock.gif 7 
InBlock.gif 8                 static  void Main( string[] args) 
InBlock.gif 9                { 
InBlock.gif10                         //为远程对象创建代理 
InBlock.gif11                         //代理的优势在于不仅可以跨域访问对象还可以跨进程,和系统,使用TCP通道 
InBlock.gif12                         try 
InBlock.gif13                        { 
InBlock.gif14                                /** ///// 
InBlock.gif15                                RemoteObject.MyRemoteObject proxyObjectTcp = (RemoteObject.MyRemoteObject)Activator.GetObject( typeof(RemoteObject.MyRemoteObject), System.Configuration.ConfigurationSettings.AppSettings[ "ServiceURLTcp"]); 
InBlock.gif16                                 //通过代理访问对象的方法,输出结果 
InBlock.gif17                                Console.WriteLine( "This call object by TcpChannel,100+200 = {0}", proxyObjectTcp.AddForTcpTest(100, 200)); 
InBlock.gif18                                 
InBlock.gif19                                /** /////// 
InBlock.gif20                                RemoteObject.MyRemoteObject proxyObjectHttp = (RemoteObject.MyRemoteObject)Activator.GetObject( typeof(RemoteObject.MyRemoteObject), System.Configuration.ConfigurationSettings.AppSettings[ "ServiceURLHttp"]); 
InBlock.gif21                                 //通过代理访问对象的方法,输出结果 
InBlock.gif22                                Console.WriteLine( "This call object by HttpChannel,100-200 = {0}", proxyObjectHttp.MinusForHttpTest(100, 200)); 
InBlock.gif23                                 
InBlock.gif24                                /** ///// 注册一个远程对象的客户端代理. 
InBlock.gif25                                 //System.Runtime.Remoting.WellKnownClientTypeEntry remoteType = new System.Runtime.Remoting.WellKnownClientTypeEntry(typeof(RemoteObject.MyRemoteObject), "ipc://FrankTestIpc/RemoteObject.MyRemoteObject"); 
InBlock.gif26                                 //System.Runtime.Remoting.RemotingConfiguration.RegisterWellKnownClientType(remoteType);//如果需要客户端和住进程通讯,要在客户端注册代理,方式和服务器端注册注册远程对象的代理相同 
InBlock.gif27 
InBlock.gif28                                RemoteObject.MyRemoteObject proxyObjectIpc = (RemoteObject.MyRemoteObject)Activator.GetObject( typeof(RemoteObject.MyRemoteObject), System.Configuration.ConfigurationSettings.AppSettings[ "ServiceURLIpc"]); 
InBlock.gif29                                 //通过代理访问对象的方法,输出结果 
InBlock.gif30                                Console.WriteLine( "This call object by IpcChannel,100*200 = {0}", proxyObjectIpc.MultipleForIpcTest(100, 200)); 
InBlock.gif31                        } 
InBlock.gif32                         catch (Exception e) 
InBlock.gif33                        { 
InBlock.gif34                                 throw e; 
InBlock.gif35                        } 
InBlock.gif36                         finally    
InBlock.gif37                        { 
InBlock.gif38 
InBlock.gif39                        } 
InBlock.gif40                         //For Debug 
InBlock.gif41                        Console.WriteLine( "Press any key to exit!"); 
InBlock.gif42                        Console.ReadLine(); 
InBlock.gif43                } 
InBlock.gif44 
InBlock.gif45        } 
InBlock.gif46}
       主进程通过配置获取远程对象的信息,为远程对象创建代理,代理的优势在于不仅可以跨域访问对象还可以跨进程,和系统,使用TCP通道,降低系统耦合性.最后客户端通过代理访问远程对象的方法,输出结果.首先要运行服务器端,其次是客户端,IDE使用的是Visual Studio 2005/2008.其次注意项目引用.运行后的结果显示如下.
服务器:
     显示3个通道都注册成功.
客户端:
  客户端分别通过3种方式调用远程对象,进行运算.测试成功!
本文代码下载. /Files/frank_xl/NetRemoting.rar
小结:以上就是全部的.Net Remoting的实现过程.当然.Net Remoting知识范围很广,还有异步调用,安全等.以后再做深入的学习.接下来一节我打算写关于Enterprise Services的文章,其中会涉及到COM+的知识,如COM+中事务机制.我们有必要好好学习一下.希望本文的能给大家在WCF学习上对.Net Remoting技术的理解有所帮助.大家有问题可以一起交流~



 本文转自 frankxulei 51CTO博客,原文链接:http://blog.51cto.com/frankxulei/320394,如需转载请自行联系原作者



相关文章
|
4天前
|
人工智能 量子技术 C#
【专栏】.NET 开发:开启数字化新时代
【4月更文挑战第29天】.NET开发在数字化新时代中发挥关键作用,借助跨平台能力、高性能和现代编程语言支持,如C#,助力企业实现数字化转型。通过企业级应用开发、移动应用和云计算集成,.NET加速业务流程和提升用户体验。未来,.NET将涉足AI、ML、MR/AR及量子计算,持续推动技术创新和数字化转型。开发者应提升技能,适应高性能需求,把握发展机遇。
|
4天前
|
缓存 监控 算法
【专栏】.NET 开发:实现卓越性能的途径
【4月更文挑战第29天】本文探讨了.NET开发中的性能优化,强调了理解性能问题根源和使用分析工具的重要性。基础优化包括代码优化(如减少计算、避免内存泄漏)、资源管理及选择合适算法。高级策略涉及并行编程、缓存策略、预编译(AOT)和微服务架构。持续性能测试与监控是关键,包括性能测试、监控分析和建立优化反馈循环。开发者应持续学习和实践性能优化,以构建高性能应用。
|
4天前
|
开发框架 .NET C#
【专栏】理解.NET 技术,提升开发水平
【4月更文挑战第29天】本文介绍了.NET技术的核心概念和应用,包括其跨平台能力、性能优化、现代编程语言支持及Web开发等特性。文章强调了深入学习.NET技术、关注社区动态、实践经验及学习现代编程理念对提升开发水平的重要性。通过这些,开发者能更好地利用.NET构建高效、可维护的多平台应用。
|
4天前
|
机器学习/深度学习 vr&ar 开发者
【专栏】.NET 技术:引领开发新方向
【4月更文挑战第29天】本文探讨了.NET技术如何引领软件开发新方向,主要体现在三方面:1) 作为跨平台开发的先锋,.NET Core支持多操作系统和移动设备,借助.NET MAUI创建统一UI,适应物联网需求;2) 提升性能和开发者生产力,采用先进技术和优化策略,同时更新C#语言特性,提高代码效率和可维护性;3) 支持现代化应用架构,包括微服务、容器化,集成Kubernetes和ASP.NET Core,保障安全性。此外,.NET还不断探索AI、ML和AR/VR技术,为软件开发带来更多创新可能。
|
4天前
|
物联网 vr&ar 开发者
【专栏】.NET 技术:为开发注入活力
【4月更文挑战第29天】本文探讨了.NET技术的创新,主要体现在三个方面:1) .NET Core实现跨平台开发革命,支持多种操作系统和硬件,如.NET MAUI用于多平台UI;2) 性能提升与生产力飞跃,C#新特性简化编程,JIT和AOT优化提升性能,Roslyn提供代码分析工具;3) 引领现代化应用架构,支持微服务、容器化,内置安全机制。未来,.NET 7将带来更多新特性和前沿技术整合,如量子计算、AI,持续推动软件开发创新。开发者掌握.NET技术将赢得竞争优势。
|
4天前
|
人工智能 前端开发 Cloud Native
【专栏】洞察.NET 技术的开发趋势
【4月更文挑战第29天】本文探讨了.NET技术的三大发展趋势:1) 跨平台与云原生技术融合,通过.NET Core支持轻量级、高性能应用,适应云计算和微服务;2) 人工智能与机器学习的集成,如ML.NET框架,使开发者能用C#构建AI模型;3) 引入现代化前端开发技术,如Blazor,实现前后端一致性。随着.NET 8等新版本的发布,期待更多创新技术如量子计算、AR/VR的融合,.NET将持续推动软件开发的创新与进步。
|
4天前
|
开发框架 物联网 测试技术
【专栏】.NET 开发:打造领先应用的基石
【4月更文挑战第29天】本文探讨了.NET开发框架为何成为构建领先应用的首选。高性能与稳定性是.NET的核心优势,它采用先进的技术和优化策略,如.NET Core的轻量级设计和JIT/AOT编译模式。跨平台兼容性让开发者能用相同代码库在不同操作系统上构建应用。现代化的开发体验,如C#语言的创新特性和Visual Studio的强大工具,提升了开发者生产力。丰富的生态系统和广泛支持,包括庞大的开发者社区和微软的持续投入,为.NET提供了坚实后盾。
|
4天前
|
人工智能 前端开发 Devops
【专栏】洞察.NET 技术在现代开发中的作用
【4月更文挑战第29天】本文探讨了.NET技术在现代软件开发中的核心价值、应用及挑战。.NET提供语言统一性与多样性,强大的Visual Studio工具,丰富的类库,跨平台能力及活跃的开发者社区。实际应用包括企业级应用、Web、移动、云服务和游戏开发。未来面临性能优化、容器化、AI集成等挑战,需持续创新。开发者应深入理解.NET,把握技术趋势,参与社区,共创美好未来。
|
4天前
|
机器学习/深度学习 人工智能 开发者
【专栏】.NET 技术:为开发带来新机遇
【4月更文挑战第29天】本文探讨了.NET技术如何为软件开发带来新机遇,分为三个部分:首先,.NET的跨平台革命,包括.NET Core的兴起、Xamarin与.NET MAUI的移动应用开发、开源社区的推动及性能优化;其次,介绍了云服务与微服务架构的集成,如Azure云服务、微服务支持、DevOps与CI/CD,以及Docker容器化;最后,讨论了AI与机器学习集成,如ML.NET、认知服务、TensorFlow和ONNX,使开发者能构建智能应用。面对这些机遇,开发者应不断学习和适应新技术,以创造更多价值。
|
4天前
|
算法 Java 编译器
【专栏】.NET 开发:实现高效能的秘诀
【4月更文挑战第29天】本文探讨了提升.NET应用性能的三个方面:理解.NET运行时(垃圾回收、JIT编译器、异步编程和线程并发)、优化代码与算法(代码细节、数据结构选择和算法效率)以及利用工具和框架(性能分析工具、高性能库和CI/CD流程)。通过深入学习、合理设计和有效工具,开发者可实现.NET应用的高效能。