|
s Foo : MarshalByRefObject {
public override Object InitializeLifetimeService()
{
ILease lease = (ILease)base.InitializeLifetimeService();
if (lease.CurrentState == LeaseState.Initial) {
lease.InitialLeaseTime = TimeSpan.FromMinutes(1);
lease.SponsorshipTimeout = TimeSpan.FromMinutes(2);
lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
}
return lease;
}
}
只有当租用处于初始状态时,才可以更改租用属性。InitializeLifetimeService 的实现通常调用基类的相应方法,来检索远程对象的现有租用。如果在此之前从未对该对象封送过,则返回的租用会处于其初始状态且可以设置租用属性。一旦封送了对象,则租用会从初始状态变为激活状态,并忽略任何初始化租用属性的尝试(但有一种情况例外)。激活远程对象时将调用 InitializeLifetimeService。通过激活调用可以提供一个租用发起者的列表,而且当租用处于激活状态时,可以随时将其他发起者添加到列表中。
可以下列方式延长租用时间:
- 客户端可以调用 Lease 类上的 Renew 方法。
- 租用可以向某个发起者请求 Renewal。
- 当客户端调用对象上的某个方法时,RenewOnCall 值会自动更新租用。
一旦租用过期,其内部状态会由 Active 变为 Expired,且不再对发起者进行任何调用,对象也会被作为垃圾回收。一般情况下,如果发起者分散在 Web 上或位于某个防火墙的后面,远程对象回叫发起者时会遇到困难。因此,发起者不必与客户端处于同一位置,只要远程对象能够访问得到,它可以为网络上的任意位置。
通过租用来管理远程对象的生存期可以作为引用计数的一种替代方法,因为当网络连接的性能不可靠时,引用计数会显得复杂和低效。尽管有人会坚持认为远程对象的生存期比所需的时间要长,但与引用计数和连接客户相比,租用降低了网络的繁忙程度,将会成为一种非常受欢迎的解决方案。
总结
要提供完美的、能够满足大多数商务应用需求的远程处理框架,即使能够做到,也必然会非常困难。Microsoft 提供了能够根据需要进行扩展和自定义的框架,在正确的方向上迈出了关键的一步。
附录 A:使用 TCP 通道进行远程处理的示例
此附录显示了如何编写简单的“Hello World”远程应用程序。客户端将一个字符串传递到远程对象上,该远程对象将单词“Hi There”附加到字符串上,并将结果返回到客户端。
将此文件保存为 server.cs。此处为服务器的代码: using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels.TCP;
namespace RemotingSamples {
public class HelloServer : IHello {
public static int Main(string [] args) {
TCPChannel chan = new TCPChannel(8085);
ChannelServices.RegisterChannel(chan);
RemotingServices.RegisterWellKnownType(
"server", "RemotingSamples.HelloServer", "SayHello", WellKnownObjectMode.SingleCall);
System.Console.WriteLine("请按 <enter> 键退出...");
System.Console.ReadLine();
return 0;
}
public HelloServer()
{
Console.WriteLine("HelloServer 已激活");
}
~HelloServer()
{
Console.WriteLine("对象已清除");
}
public ForwardMe HelloMethod(ForwardMe obj)
{
Console.WriteLine("Hello.HelloMethod : {0}", name);
return "Hi there " + name;
}
}
}
将此代码保存为 client.cs: using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels.TCP;
namespace RemotingSamples {
public class Client
{
public static int Main(string [] args)
{
TCPChannel chan = new TCPChannel();
ChannelServices.RegisterChannel(chan);
ForwardMe param = new ForwardMe();
HelloServer obj = (HelloServer)Activator.GetObject(
typeof(RemotingSamples.HelloServer), "tcp://localhost:8085/SayHello");
if (obj == null) System.Console.WriteLine("无法定位服务器");
else {
Console.WriteLine("值为 " + param.getValue());
ForwardMe after = obj.HelloMethod(param);
Console.WriteLine("呼叫后的值为 " + after.getValue());
}
return 0;
}
}
}
下面是 makefile: all: server.exe client.exe share.dll
share.dll: share.cs
csc /debug+ /target:library /out:share.dll share.cs
server.exe: server.cs
csc /debug+ /r:share.dll /r:System.Runtime.Remoting.dll server.cs
client.exe: client.cs server.exe
csc /debug+ /r:share.dll /r:server.exe /r:System.Runtime.Remoting.dll client.cs
clean:
@del server.exe client.exe *.pdb *~ *.*~
附录 B:使用 HTTP 通道进行远程处理的示例
将此文件保存为 server.cs。此处为服务器的代码: using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels.HTTP;
namespace RemotingSamples {
public class HelloServer : IHello {
public static int Main(string [] args) {
HTTPChannel chan = new HTTPChannel(8085);
ChannelServices.RegisterChannel(chan);
RemotingServices.RegisterWellKnownType(
"server", "RemotingSamples.HelloServer", "SayHello", WellKnownObjectMode.SingleCall);
System.Console.WriteLine("请按 <enter> 键退出...");
System.Console.ReadLine();
return 0;
}
public HelloServer()
{
Console.WriteLine("HelloServer 已激活");
}
~HelloServer()
{
Console.WriteLine("对象已清除");
}
public ForwardMe HelloMethod(ForwardMe obj)
{
Console.WriteLine("Hello.HelloMethod : {0}", name);
return "Hi there " + name;
}
}
}
将此代码保存为 client.cs: using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels.HTTP;
namespace RemotingSamples {
public class Client
{
public static int Main(string [] args)
{
HTTPChannel chan = new HTTPChannel();
ChannelServices.RegisterChannel(chan);
ForwardMe param = new ForwardMe();
HelloServer obj = (HelloServer)Activator.GetObject(
typeof(RemotingSamples.HelloServer), "http://localhost:8085/SayHello");
if (obj == null) System.Console.WriteLine("无法定位服务器");
else {
Console.WriteLine("值为 " + param.getValue());
ForwardMe after = obj.HelloMethod(param);
Console.WriteLine("呼叫后的值为 " + after.getValue());
}
return 0;
}
}
}
下面是 makefile: all: server.exe client.exe share.dll
share.dll: share.cs
csc /debug+ /target:library /out:share.dll share.cs
server.exe: server.cs
csc /debug+ /r:share.dll /r:System.Runtime.Remoting.dll server.cs
client.exe: client.cs server.exe
csc /debug+ /r:share.dll /r:server.exe /r:System.Runtime.Remoting.dll client.cs
clean:
@del server.exe client.exe *.pdb *~ *.*~
|