【Frank.Xu】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应

用中,支持对象的跨域边界访问.具体代码如下:

Code
 1namespace RemoteObject
 2{
 3    //创建远程对象.继承MarshalByRefObject,可以使用在

remoting应用中,支持对象的跨域边界访问
 4    public class MyRemoteObject : MarshalByRefObject//访

问远程对象需要通过代理
 5    {
 6        //简单的例子,实现加法功能的方法AddForTcpTest,这

个远程对象可以实现封装业务逻辑或者数据访问等操作。
 7        //
 8        public int AddForTcpTest(int a, int b)
 9        {
10            return a + b;
11        }
12        //实现减法功能的方法MinusForHttpTest,测试HTTP通道


13        public int MinusForHttpTest(int a, int b)
14        {
15            return a - b;
16        }
17        //实现乘法功能的方法MultipleForIpcTest,测试Ipc通


18        public int MultipleForIpcTest(int a, int b)
19        {
20            return a * b;
21        }
22    }
23
24}
25
 

      对象分别定义了3种方法,目的是为了测试3种不同的通道方式

的效果. //简单的例子,实现加法功能的方法AddForTcpTest,这个

远程对象可以实现封装业务逻辑或者数据访问等操作。实现减法功

能的方法MinusForHttpTest,测试HTTP通道。实现乘法功能的方法

MultipleForIpcTest,测试Ipc通道.

     2服务器端,注册通道,以便进程间通信,我们这里注册了三种通

道,分别是HttpChanel\TcpChanel\IPCChanel.具体代码如下:

 

Code
 1namespace NetRemotingHost
 2{
 3    class NetRemotingHost
 4    {
 5        //创建宿主应用程序
 6        static void Main(string[] args)
 7        {
 8
 9            /**///创

建三种通道/
10            ///创建Tcp通道,使用端口10001
11            TcpChannel chanTcp = new TcpChannel(10001);
12            /**创建Http通道,使用端口10002
13            HttpChannel chanHttp = new HttpChannel

(10002);
14            /**创建IPC通道,使用端口10003,IPC只适合同

系统内进程的通信,所以不需要设置端口和主机名
15            IpcChannel chanIPC = new IpcChannel

("FrankTestIpc");
16            /**///注

册通道//
17
18            ///注册TCP通道
19            ChannelServices.RegisterChannel(chanTcp);
20            /**注册HTTP通道
21            ChannelServices.RegisterChannel(chanHttp);
22            /**注册IPC通道
23            ChannelServices.RegisterChannel(chanIPC);
24
25            /**/

打印通道/
26            // 打印TCP通道的名称.
27            Console.WriteLine("The name of the TCPChannel

is {0}.",
28                chanTcp.ChannelName);
29            // 打印TCP通道的优先级.
30            Console.WriteLine("The priority of the

TCPChannel is {0}.",
31                chanTcp.ChannelPriority);
32
33            // 打印Http通道的名称.
34            Console.WriteLine("The name of the

HttpChannel is {0}.",
35                chanTcp.ChannelName);
36            // 打印Http通道的优先级.
37            Console.WriteLine("The priority of the

HttpChannel is {0}.",
38                chanTcp.ChannelPriority);
39
40            // 打印IPC通道的名称.
41            Console.WriteLine("The name of the IpcChannel

is {0}.",
42                chanTcp.ChannelName);
43            // 打印IPC通道的优先级.
44            Console.WriteLine("The priority of the

IpcChannel is {0}.",
45                chanTcp.ChannelPriority);
46           

/**注册对

象/
47            //注册对象MyRemoteObject到Net Remoting运行库
48            //配置远程通信基础框架.第2个参数是对象的URI,

“RemoteObject.MyRemoteObject”,客户端URL一定要和这个匹配

,不然会出现查找不到代理对象的异常
49           

RemotingConfiguration.RegisterWellKnownServiceType(typeof

(RemoteObject.MyRemoteObject),

"RemoteObject.MyRemoteObject",

WellKnownObjectMode.Singleton);
50            //远程对象激活方式是单件激活模式,每次调用共

享一个对象,SingleCall激活模式会在每次调用的时候产生一个新

对象
51
52            //向信道暴露一个IPC远程对象.
53           

//RemotingConfiguration.RegisterWellKnownService(Type

(typeof(RemoteObject), "RemoteObject.rem",

System.Runtime.Remoting.WellKnownObjectMode.Singleton);
54
55            /**For

Debug//

///
56            Console.WriteLine("Press any key to exit!");
57            System.Console.ReadLine();
58
59        }
60
61
62    }
63}
64

            创建Tcp通道,使用端口10001, 创建Http通道,使用端

口10002,创建IPC通道,使用端口10003,IPC只适合同系统内进程的

通信,所以不需要设置端口和主机名.然后调用ChannelServices类

的静态方法RegisterChannel进行注册.最后一步注册对象

MyRemoteObject到Net Remoting运行库,同时要先配置远程通信基础

框架.第2个参数是对象的URI,“RemoteObject.MyRemoteObject”

,客户端URL一定要和这个匹配,不然会出现查找不到代理对象的异

常.WellKnownObjectMode.Singleton);远程对象激活方式是单件激

活模式,每次调用共享一个对象,SingleCall激活模式会在每次调

用的时候产生一个新对象.

     3客户端是控制台程序(实际项目类型可以替换,这里只是为了

作为例子选择控制台类型).配置文件进行的设置如下:

Code
 1
 2   
 3       

value="tcp://localhost:10001/RemoteObject.MyRemoteObject"/>
 4       

value="http://localhost:10002/RemoteObject.MyRemoteObject"/

>
 5       

value="ipc://FrankTestIpc/RemoteObject.MyRemoteObject"/>
 6   


 7   
 8          
 9      
10
     配置文件设置的是具体通道的URL信息.具体c#实现代码如下:

Code
 1
 2namespace RemoteClient
 3{
 4    class MyClient//客户端
 5    {
 6        [STAThread]//主线程,建立客户端程序:注册通道,根

据URL得到对象代理,使用代理调用远程对象
 7
 8        static void Main(string[] args)
 9        {
10            //为远程对象创建代理
11            //代理的优势在于不仅可以跨域访问对象还可以跨

进程,和系统,使用TCP通道
12            try
13            {
14                /**/
15                RemoteObject.MyRemoteObject

proxyObjectTcp = (RemoteObject.MyRemoteObject)

Activator.GetObject(typeof(RemoteObject.MyRemoteObject),

System.Configuration.ConfigurationSettings.AppSettings

["ServiceURLTcp"]);
16                //通过代理访问对象的方法,输出结果
17                Console.WriteLine("This call object by

TcpChannel,100+200 = {0}", proxyObjectTcp.AddForTcpTest

(100, 200));
18               
19                /**///
20                RemoteObject.MyRemoteObject

proxyObjectHttp = (RemoteObject.MyRemoteObject)

Activator.GetObject(typeof(RemoteObject.MyRemoteObject),

System.Configuration.ConfigurationSettings.AppSettings

["ServiceURLHttp"]);
21                //通过代理访问对象的方法,输出结果
22                Console.WriteLine("This call object by

HttpChannel,100-200 = {0}",

proxyObjectHttp.MinusForHttpTest(100, 200));
23               
24                /**/ 注册一个远程对象的客户端代理.
25               

//System.Runtime.Remoting.WellKnownClientTypeEntry

remoteType = new

System.Runtime.Remoting.WellKnownClientTypeEntry(typeof

(RemoteObject.MyRemoteObject),

"ipc://FrankTestIpc/RemoteObject.MyRemoteObject");
26               

//System.Runtime.Remoting.RemotingConfiguration.RegisterWel

lKnownClientType(remoteType);//如果需要客户端和住进程通讯,

要在客户端注册代理,方式和服务器端注册注册远程对象的代理相


27
28                RemoteObject.MyRemoteObject

proxyObjectIpc = (RemoteObject.MyRemoteObject)

Activator.GetObject(typeof(RemoteObject.MyRemoteObject),

System.Configuration.ConfigurationSettings.AppSettings

["ServiceURLIpc"]);
29                //通过代理访问对象的方法,输出结果
30                Console.WriteLine("This call object by

IpcChannel,100*200 = {0}",

proxyObjectIpc.MultipleForIpcTest(100, 200));
31            }
32            catch (Exception e)
33            {
34                throw e;
35            }
36            finally
37            {
38
39            }
40            //For Debug
41            Console.WriteLine("Press any key to exit!");
42            Console.ReadLine();
43        }
44
45    }
46}
47
      主进程通过配置获取远程对象的信息,为远程对象创建代理,

代理的优势在于不仅可以跨域访问对象还可以跨进程,和系统,使用

TCP通道,降低系统耦合性.最后客户端通过代理访问远程对象的方法

,输出结果.首先要运行服务器端,其次是客户端,IDE使用的是

Visual Studio 2005/2008.其次注意项目引用.运行后的结果显示如

下.

服务器:

 

     显示3个通道都注册成功.

客户端:

 

     客户端分别通过3种方式调用远程对象,进行运算.测试成功!

本文代码下载./Files/frank_xl/NetRemoting.rar

小结:以上就是全部的.Net Remoting的实现过程.当然.Net

Remoting知识范围很广,还有异步调用,安全等.以后再做深入的学习

.接下来一节我打算写关于Enterprise Services的文章,其中会涉及

到COM+的知识,如COM+中事务机制.我们有必要好好学习一下.希望本

文的能给大家在WCF学习上对.Net Remoting技术的理解有所帮助.大

家有问题可以一起交流~

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/15783504/viewspace-555166/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/15783504/viewspace-555166/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值