ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 【Frank.Xu】WCF分布式开发必备知识(2):.Net Remoting

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

原创 Linux操作系统 作者:依旧伊利丹 时间:2009-02-18 11:20:25 0 删除 编辑

上一节我们学习了网络分布式编程中的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博客 ” ,链接:https://blog.itpub.net/15783504/viewspace-555166/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-09-23

  • 博文量
    26
  • 访问量
    98005