这几天一直在学习Remoting,在网上也看了许多达人们的贴子,觉得他们写的都很好,可是没有一篇介绍了我需要的全部内容,只是各有各的侧重点,为了备忘,将这些贴子的内容进行了一下综合,算是学习的笔记吧,作为备忘的内容,以防以后有些东西记不起来的时候,过来翻一翻。有理解上有错的地方,欢迎大家指正
一、Remoting 的含义
Remoting就是远程的意思,也就是说允许你跨应用程序域、跨机器,甚至是跨局域网去访问、调用远程的对象。
二、Remoting的通道
要跨域访问远程对象,就会涉及通信的问题,而两边进行通信的中介就是通道。Remoting 的通道主要有两种:Tcp 和Http。Tcp 通道是基于Socket的,通过Tcp 协议来传输消息流;Http通道是是通过Http协议来传输消息流的,它有一个最大的优点就是可以穿过防火墙。
所以如果要写局域网内的Remoting程序,可以采用Tcp通道,速度快;如果是互联网的,需要穿过防火墙的,就要使用Http通道。
三、Remoting的操作流程
在服务器端声明一个对象(Object),注册一个通道,并把Object发布到通道中,等待客户端来取这个对象。客户端也注册同样的通道,取得这个对象Object(并非真的是Object本身,只是一个代理而已),这时在客户端就可以像使用本地对象一样使用Object这个远程对象了。
1、声明对象
这一步很简单,就是创建一个类而已。需要注意的由于这个类的实例在远程传递,所以需要要继承自MarshalByRefObject这个基类。最好把需要远程传递的对象封装在同一个Dll中,因为服务器端和客户端都要有这些类的签名。如果某个需要远程传递的对象只是一个结构(struct),在你的业务逻辑上只是用到其中的数据,而不需要调用其方法,也可以不继承MarshalByRefObject,但要在其定义的地方加上[Serializable]属性,以便能够将其序列化。
2、注册通道
在服务器端发布这个Object的时候,它可以是已实例化的,也可以是未实例化的(只是提供Object的类型,并未对其初始化,也即并未调用它的构造函数)
先说未实例化的情况:
比如我定义了一个类Say,为方便起见,用接口ISay表示其具体实现,如下:
1)服务器端激活又叫做WellKnow方式,很多又翻译为知名对象。顾名思义,这个对象的实例化操作是在服务器端进行的。为什么称为知名对象激活模式呢?是因为服务器应用程序在激活对象实例之前会在一个众所周知的统一资源标识符(URI)上来发布这个类型。然后该服务器进程会为此类型配置一个WellKnown对象,并根据指定的端口或地址来发布对象。
服务器端面激活又分为两种模式:SingleTon和SingleCall
SingleTon模式:SingleTon模式为所有的客户端提供同一个对象,类似于全局变量,是一种有状态的模式,即一个客户端对这个对象所做的修改,会影响到另一个客户端对这个对象的访问。举例来说,如果一个远程对象有一个累加方法(i=0;++i),被多个客户端(例如两个)调用。如果设置为SingleTon方式,则第一个客户获得值为1,第二个客户获得值为2,因为他们获得的对象实例是相同的。如果熟悉Asp.Net的状态管理,我们可以认为它是一种Application状态。
SingleCall 模式:SingleCall是一种无状态模式。一旦设置为SingleCall模式,则当客户端调用远程对象的方法时,Remoting会为每一个客户端建立一个远程对象实例,至于对象实例的销毁则是由GC自动管理的。同上一个例子而言,则访问远程对象的两个客户获得的都是1。我们仍然可以借鉴Asp.Net的状态管理,认为它是一种Session状态。
一、Remoting 的含义
Remoting就是远程的意思,也就是说允许你跨应用程序域、跨机器,甚至是跨局域网去访问、调用远程的对象。
二、Remoting的通道
要跨域访问远程对象,就会涉及通信的问题,而两边进行通信的中介就是通道。Remoting 的通道主要有两种:Tcp 和Http。Tcp 通道是基于Socket的,通过Tcp 协议来传输消息流;Http通道是是通过Http协议来传输消息流的,它有一个最大的优点就是可以穿过防火墙。
所以如果要写局域网内的Remoting程序,可以采用Tcp通道,速度快;如果是互联网的,需要穿过防火墙的,就要使用Http通道。
三、Remoting的操作流程
在服务器端声明一个对象(Object),注册一个通道,并把Object发布到通道中,等待客户端来取这个对象。客户端也注册同样的通道,取得这个对象Object(并非真的是Object本身,只是一个代理而已),这时在客户端就可以像使用本地对象一样使用Object这个远程对象了。
1、声明对象
这一步很简单,就是创建一个类而已。需要注意的由于这个类的实例在远程传递,所以需要要继承自MarshalByRefObject这个基类。最好把需要远程传递的对象封装在同一个Dll中,因为服务器端和客户端都要有这些类的签名。如果某个需要远程传递的对象只是一个结构(struct),在你的业务逻辑上只是用到其中的数据,而不需要调用其方法,也可以不继承MarshalByRefObject,但要在其定义的地方加上[Serializable]属性,以便能够将其序列化。
2、注册通道
1 //Tcp通道
2 TcpChannel channel=new TchChannel(8080);
3 ChannelServices.RegisterChannel(channel, false);
4 //Http通道
5 HttpChannel channel = new HttpChannel(8080);
6 ChannelServices.RegisterChannel(channel, false);
7
3、发布远程对象2 TcpChannel channel=new TchChannel(8080);
3 ChannelServices.RegisterChannel(channel, false);
4 //Http通道
5 HttpChannel channel = new HttpChannel(8080);
6 ChannelServices.RegisterChannel(channel, false);
7
在服务器端发布这个Object的时候,它可以是已实例化的,也可以是未实例化的(只是提供Object的类型,并未对其初始化,也即并未调用它的构造函数)
先说未实例化的情况:
比如我定义了一个类Say,为方便起见,用接口ISay表示其具体实现,如下:
1 interface ISay
2 {
3 void SayHello();
4 }
将未实例化的对象进行实例化的过程,称为“激活”,Remoting 中有两种不同的方式2 {
3 void SayHello();
4 }
1)服务器端激活又叫做WellKnow方式,很多又翻译为知名对象。顾名思义,这个对象的实例化操作是在服务器端进行的。为什么称为知名对象激活模式呢?是因为服务器应用程序在激活对象实例之前会在一个众所周知的统一资源标识符(URI)上来发布这个类型。然后该服务器进程会为此类型配置一个WellKnown对象,并根据指定的端口或地址来发布对象。
服务器端面激活又分为两种模式:SingleTon和SingleCall
SingleTon模式:SingleTon模式为所有的客户端提供同一个对象,类似于全局变量,是一种有状态的模式,即一个客户端对这个对象所做的修改,会影响到另一个客户端对这个对象的访问。举例来说,如果一个远程对象有一个累加方法(i=0;++i),被多个客户端(例如两个)调用。如果设置为SingleTon方式,则第一个客户获得值为1,第二个客户获得值为2,因为他们获得的对象实例是相同的。如果熟悉Asp.Net的状态管理,我们可以认为它是一种Application状态。
1//服务器端发布
2RemotingConfiguration.RegisterWellKnownServiceType(typeof(ISay), "SayHello", WellKnownObjectMode.Singleton);
3
4
5//客户端调用
6ISay sayer= (ISay)Activator.GetObject(typeof(ISay), "tcp://localhost:8080/SayHello");
7sayer.SayHello();
个人认为:对象被实例化的确切时间应该是SayHello方法第一次被调用时,代理将调用信息传回服务器端,服务器端发现通道中不存在这个对象,所以就创建这个对象。2RemotingConfiguration.RegisterWellKnownServiceType(typeof(ISay), "SayHello", WellKnownObjectMode.Singleton);
3
4
5//客户端调用
6ISay sayer= (ISay)Activator.GetObject(typeof(ISay), "tcp://localhost:8080/SayHello");
7sayer.SayHello();
SingleCall 模式:SingleCall是一种无状态模式。一旦设置为SingleCall模式,则当客户端调用远程对象的方法时,Remoting会为每一个客户端建立一个远程对象实例,至于对象实例的销毁则是由GC自动管理的。同上一个例子而言,则访问远程对象的两个客户获得的都是1。我们仍然可以借鉴Asp.Net的状态管理,认为它是一种Session状态。
1//服务器端发布
2RemotingConfiguration.RegisterWellKnownServiceType(typeof(ISay), "SayHello", WellKnownObjectMode.SingleCall);
3
4
5//客户端调用
6ISay sayer= (ISay)Activator.GetObject(typeof(ISay), "tcp://localhost:8080/SayHello");
7sayer.SayHello();
2RemotingConfiguration.RegisterWellKnownServiceType(typeof(ISay), "SayHello", WellKnownObjectMode.SingleCall);
3
4
5//客户端调用
6ISay sayer= (ISay)Activator.GetObject(typeof(ISay), "tcp://localhost:8080/SayHello");
7sayer.SayHello();