.Net Remoting常用的远程对象激活模式是服务器端激活模式,又叫做WellKnow方式。
服务器端激活模式又分两种,分别是:SingleTon、和SingleCall
SingleTon、和SingleCall的区别如下:
1、SingleTon模式:此为有状态模式。如果设置为SingleTon激活方式,则Remoting将为所有客户端建立同一个对象实例。
2、SingleCall模式:SingleCall是一种无状态模式。一旦设置为SingleCall模式,则当客户端调用远程对象的方法时,Remoting会为每一个客户端建立一个远程对象实例,至于对象实例的销毁则是由GC自动管理的。
对于服务器端激活的代码实现,如下:
服务器端:
(1)、注册通道
TcpChannel channel = new TcpChannel(8080);
ChannelServices.RegisterChannel(channel); //注册通道
(2)、激活远程对象
a、如果是SingleTon模式
对于WellKnown对象,可以通过静态方法RemotingConfiguration.RegisterWellKnownServiceType() 来实现:RemotingConfiguration.RegisterWellKnownServiceType(
typeof(ServerRemoteObject.ServerObject),
"ServiceMessage",WellKnownObjectMode.SingleTon);
b、如果是SingleCall模式
注册对象的方法基本上和SingleTon模式相同,只需要将枚举参数WellKnownObjectMode改为 SingleCall就可以了。RemotingConfiguration.RegisterWellKnownServiceType(
typeof(ServerRemoteObject.ServerObject),
"ServiceMessage",WellKnownObjectMode.SingleCall);
客户端:
(1)、注册通道
TcpChannel channel = new TcpChannel();
ChannelServices.RegisterChannel(channel);
(2)、获得远程对象
ServerRemoteObject.ServerObject serverObj = (ServerRemoteObject.ServerObject) Activator.GetObject(typeof(ServerRemoteObject.ServerObject), "tcp://localhost:8080/ServiceMessage");
首先以WellKnown模式激活,客户端获得对象的方法是使用GetObject()。
以上讲的都是服务器端激活,有singleTon和singleCall两种模式,但是还有一种情况,如下:
Remoting中没有提供类似UnregisterWellKnownServiceType()的方法,也即是说,一旦通过注册了远程对象,如果没有关闭通道的话,该对象就一直存在于通道中。只要客户端激活该对象,就会创建对象实例。如果Remoting传送的只有一个远程对象,这不存在问题,关闭通道就可以了。如果传送多个远程对象呢?要关闭指定的远程对象应该怎么做?关闭之后又需要启动又该如何?
我们注意到在Remoting中提供了Marshal()和Disconnect()方法,答案就在这里。Marshal()方法是将MarshalByRefObject类对象转化为ObjRef类对象,这个对象是存储生成代理以与远程对象通讯所需的所有相关信息。这样就可以将该实例序列化以便在应用程序域之间以及通过网络进行传输,客户端就可以调用了。而Disconnect()方法则将具体的实例对象从通道中断开。
方法如下:
首先注册通道:
TcpChannel channel = new TcpChannel(8080);
ChannelServices.RegisterChannel(channel);
接着启动服务:
先在服务器端实例化远程对象。
ServerObject obj = new ServerObject();
然后,注册该对象。注意这里不用RemotingConfiguration.RegisterWellKnownServiceType(),而是使用RemotingServices.Marshal():
ObjRef objrefWellKnown = RemotingServices.Marshal(obj, "ServiceMessage");
如果要注销对象,则:
RemotingServices.Disconnect(obj);
又出现了一个问题,当注册多个通道,并且在服务器端显式实例化多个对象时,那个对象,绑定到那个通道呢?如下:
//注册第一个通道
BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();
serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
IDictionary props = new Hashtable();
props["name"] = "tcp1";
props["port"] = 8080;
TcpChannel channel = new TcpChannel(props, clientProvider, serverProvider);
ChannelServices.RegisterChannel(channel);
//再注册一个通道
BinaryServerFormatterSinkProvider serverProvider2 = new BinaryServerFormatterSinkProvider();
BinaryClientFormatterSinkProvider clientProvider2 = new BinaryClientFormatterSinkProvider();
serverProvider2.TypeFilterLevel = TypeFilterLevel.Full;
IDictionary props2 = new Hashtable();
props2["name"] = "tcp2";
props2["port"] = 8081;
TcpChannel channel2 = new TcpChannel(props2, clientProvider2, serverProvider2);
ChannelServices.RegisterChannel(channel2);
//声明第一个对象
Obj = new BroadCastObj();
Obj.i = 1;
ObjRef objRef = RemotingServices.Marshal(Obj, "tcp://localhost:8080/BroadCastMessage.soap");
//声明第二个对象
Obj2 = new BroadCastObj();
Obj2.i = 2;
ObjRef objRef2 = RemotingServices.Marshal(Obj2, "BroadCastMessage.soap2");
对象与通道之间如何配对呢?