Microsoft .Net Remoting系列教程之二:Marshal、Disconnec(2)

  租用管理器对于生命周期的设置是针对服务器上所有的远程对象。当我们通过配置文件或租用管理器设置租用的属性时,所有远程对象的生命周期都遵循该设置,除非我们对于指定的远程对象通过重写InitializeLifetimeService方法,改变了相关配置。也就是说,远程对象的租用配置优先级高于服务器端配置。

3、发起人(Sponsor)

  发起人是针对客户端而言的。远程对象就是发起人要租用的对象,发起人可以与服务器端签订租约,约定租用时间。一旦到期后,发起人还可以续租,就像现实生活中租方的契约,房东、租房者之间的关系一样。

  在.Net Framework中的System.Runtime.Remoting.Lifetime命名空间中定义了ClientSponsor类,该类继承了System.MarshalByRefObject,并实现了ISponsor接口。ClientSponsor类的属性和方法,可以参考MSDN。

  客户端要使用发起人机制,必须创建ClientSponsor类的一个实例。然后调用相关方法如Register()或Renewal()方法来注册远程对象或延长生命周期。如:

RemotingObject obj = new RemotingObject(); ClientSponsor sponsor = new ClientSponsor(); sponsor.RenewalTime = TimeSpan.FromMinutes(2); sponsor.Register(obj);

续租时间也可以在ClientSponsor的构造函数中直接设置,如:

ClientSponsor sponsor = new ClientSponsor(TimeSpan.FromMinutes(2)); sponsor.Register(obj);

我们也可以自己编写Sponsor来管理发起人机制,这个类必须继承ClientSponsor并实现ISponsor接口。

三、跟踪服务

  如前所述,我们要判断通过Marshal编组远程对象是否存在生命周期的管理。在Remoting中,可以通过跟踪服务程序来监视MBR对象的编组进程。

  我们可以创建一个简单的跟踪处理程序,该程序实现接口ITrackingHandler。接口ITrackingHandler定义了3个方法,MarshalObject、UnmarshalObject和DisconnectedObject。当远程对象被编组、解组和断开连接时,就会调用相应的方法。下面是该跟踪处理类的代码:

public class MyTracking:ITrackingHandler { public MyTracking() { // // TODO: 在此处添加构造函数逻辑 // } public void MarshaledObject(object obj,ObjRef or) { Console.WriteLine(); Console.WriteLine("对象" + obj.Tostring() + " is marshaled at " + DateTime.Now.ToShortTimeString()); } public void UnmarshaledObject(object obj,ObjRef or) { Console.WriteLine(); Console.WriteLine("对象" + obj.Tostring() + " is unmarshaled at " + DateTime.Now.ToShortTimeString()); } public void DisconnectedObject(object obj) { Console.WriteLine(obj.ToString() + " is disconnected at " + DateTime.Now.ToShortTimeString()); } }

然后再服务器端创建该跟踪处理类的实例,并注册跟踪服务:
TrackingServices.RegisterTrackingHandler(new MyTracking());

四、测试

1、建立两个远程对象,并重写InitializeLifetimeService方法:

对象一:AppService1
初始生命周期:1分钟

public class AppService1:MarshalByRefObject { public void PrintString(string contents) { Console.WriteLine(contents); } public override object InitializeLifetimeService() { ILease lease = (ILease)base.InitializeLifetimeService(); if (lease.CurrentState == LeaseState.Initial) { lease.InitialLeaseTime = TimeSpan.FromMinutes(1); lease.RenewOnCallTime = TimeSpan.FromSeconds(20); } return lease; } }

对象二:AppService2
初始生命周期:3分钟

public class AppService2:MarshalByRefObject { public void PrintString(string contents) { Console.WriteLine(contents); } public override object InitializeLifetimeService() { ILease lease = (ILease)base.InitializeLifetimeService(); if (lease.CurrentState == LeaseState.Initial) { lease.InitialLeaseTime = TimeSpan.FromMinutes(3); lease.RenewOnCallTime = TimeSpan.FromSeconds(40); } return lease; } }

为简便起见,两个对象的方法都一样。

2、服务器端

(1) 首先建立如上的监控处理类;

(2) 注册通道:

TcpChannel channel = new TcpChannel(8080); ChannelServices.RegisterChannel(channel);

(3) 设置租用管理器的初始租用时间为无限:

LifetimeServices.LeaseTime = TimeSpan.Zero;

(4) 创建该跟踪处理类的实例,并注册跟踪服务:

TrackingServices.RegisterTrackingHandler(new MyTracking());

(5) 编组两个远程对象:

ServerAS.AppService1 service1 = new ServerAS1.AppService1(); ObjRef objRef1 = RemotingServices.Marshal((MarshalByRefObject)service1,"AppService1"); ServerAS.AppService2 service2 = new ServerAS1.AppService2(); ObjRef objRef2 = RemotingServices.Marshal((MarshalByRefObject)service2,"AppService2");

(6) 使服务器端保持运行:

Console.WriteLine("Remoting服务启动,按退出..."); Console.ReadLine();

3、客户端

通过Activator.GetObject()获得两个远程对象,并调用其方法PrintString。代码略。

4、运行测试:

运行服务器端和客户端,由于监控程序将监视远程对象的编组进程,因此在运行开始,就会显示远程对象已经被Marshal:

/uploads/allimg/200612/1G03135Y_0.gif

然后再客户端调用这两个远程对象的PrintString方法,服务器端接受字符串:

/uploads/allimg/200612/1G032ST_0.gif

一分钟后,远程对象一自动被Disconnect:

/uploads/allimg/200612/1G032R59_0.gif

此时客户端如要调用远程对象一,会抛出RemotingException异常;

又一分钟后,远程对象二被Disconnect了:

/uploads/allimg/200612/1G033P32_0.gif

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wjypyd.html