远程处理示例:生存期

本主题介绍一项传统技术,保留该技术是为了向后兼容现有的应用程序,不建议对新的开发使用该技术。现在应该使用  Windows Communication Foundation (WCF) 来开发分布式应用程序。

下面的代码示例演示几个生存期租约方案。Client.exe 注册一个主办方(在初始租约时间之后),该主办方将租约续订不同于 ClientActivatedType.InitializeLifetimeService() 中所指定的 TimeSpan。请注意,MyClientSponsor 扩展 MarshalByRefObject 以便通过对租约管理器(位于 Server.exe 应用程序域中)的引用进行传递。此应用程序可以在一台计算机上运行,也可以在网络上运行。如果要在网络上运行此应用程序,必须用远程计算机的名称替换客户端配置中的**“localhost”**。

6tkeax11.Caution(zh-cn,VS.100).gif警告:
.NET 远程处理在默认情况下不执行身份验证或加密。因此,在与客户端或服务器进行远程交互之前,建议您先执行所有必要的步骤来验证它们的身份。由于 .NET 远程处理应用程序需要 FullTrust 权限才能执行,因此未经授权的客户端一旦获得服务器的访问权限,它就可以像完全受信任的客户端一样执行代码。应始终验证终结点的身份并对通信流加密,通过在 Internet Information Services (IIS) 中承载远程类型,或者通过生成自定义信道接收器对,可以完成这项工作。

运行 Server.exe,再运行 Client.exe,接着您应该可以看到与以下内容类似的输出:

Server.exe:

C:\projects\Lifetime\Server\bin>server

The server is listening. Press Enter to exit....

ClientActivatedType.RemoteMethod called.

Client.exe:

C:\projects\Lifetime\Client\bin>client

Client-activated object: RemoteMethod called. MyDomain\SomeUser

Press Enter to end the client application domain.

I've been asked to renew the lease.

Time since last renewal:00:00:09.9432506

I've been asked to renew the lease.

Time since last renewal:00:00:29.9237760

编译此示例

  1. 在命令提示符处,键入下列命令:

    csc /t:library RemoteType.cs
    csc /r:System.Runtime.Remoting.dll /r:RemoteType.dll server.cs
    csc /r:System.Runtime.Remoting.dll /r:RemoteType.dll client.cs
    
    vbc /t:library RemoteType.vb
    vbc /r:System.Runtime.Remoting.dll /r:RemoteType.dll server.vb
    vbc /r:System.Runtime.Remoting.dll /r:RemoteType.dll client.vb
    

RemoteType

using System;
using System.Runtime.Remoting.Lifetime;
using System.Security.Principal;

namespace RemoteType
{
    public class ClientActivatedType : MarshalByRefObject
    {
        public override Object InitializeLifetimeService()
        {
            ILease lease = (ILease)base.InitializeLifetimeService();

            // Normally, the initial lease time would be much longer.
            // It is shortened here for demonstration purposes.
            if (lease.CurrentState == LeaseState.Initial)
            {
                lease.InitialLeaseTime = TimeSpan.FromSeconds(3);
                lease.SponsorshipTimeout = TimeSpan.FromSeconds(10);
                lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
            }
            return lease;
        }

        public string RemoteMethod()
        {
            // Announces to the server that the method has been called.
            Console.WriteLine("ClientActivatedType.RemoteMethod called.");

            // Reports the client identity name.
            return "RemoteMethod called. " + WindowsIdentity.GetCurrent().Name;
        }
    }
}
Imports System
Imports System.Runtime.Remoting.Lifetime
Imports System.Security.Principal

Namespace RemoteType
Public Class ClientActivatedType
    Inherits MarshalByRefObject

    Public Overrides Function InitializeLifetimeService() As Object
        Dim lease As ILease = MyBase.InitializeLifetimeService()

        ' Normally, the initial lease time would be much longer.
        ' It is shortened here for demonstration purposes.
        If (lease.CurrentState = LeaseState.Initial) Then
            lease.InitialLeaseTime = TimeSpan.FromSeconds(3)
            lease.SponsorshipTimeout = TimeSpan.FromSeconds(10)
            lease.RenewOnCallTime = TimeSpan.FromSeconds(2)
        End If
        Return lease
    End Function

    Public Function RemoteMethod() As String
        Console.WriteLine("ClientActivatedType.RemoteMethod called.")

        ' Reports the client identity name.
        Return "RemoteMethod called. " & WindowsIdentity.GetCurrent().Name
    End Function

End Class
End Namespace

服务器

using System;
using System.Runtime.Remoting;

namespace Server
{
    class Program
    {
        static void Main(string[] args)
        {
            RemotingConfiguration.Configure("Server.exe.config", false);
            Console.WriteLine("The server is listening. Press Enter to exit....");
            Console.ReadLine();
        }
    }
}
Imports System
Imports System.Runtime.Remoting

Class Program
    Shared Sub Main()
        RemotingConfiguration.Configure("Server.exe.config", False)
        Console.WriteLine("The server is listening. Press Enter to exit....")
        Console.ReadLine()
    End Sub
End Class

Server.exe.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.runtime.remoting>
    <application>
      <channels>
        <channel ref="tcp" port="1234">
          <serverProviders>
            <formatter ref="binary" typeFilterLevel="Full"/>
          </serverProviders>
          <clientProviders>
            <formatter ref="binary"/>
          </clientProviders>
        </channel>
      </channels>
      <service>
        <activated type="RemoteType.ClientActivatedType, RemoteType" />
      </service>
    </application>
  </system.runtime.remoting>
</configuration>

客户端

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Lifetime;
using RemoteType;

class Client
{
    static void Main(string[] args)
    {
        RemotingConfiguration.Configure("Client.exe.config",false);
        ClientActivatedType obj = new ClientActivatedType();

        ILease lease = (ILease)obj.GetLifetimeService();
        MyClientSponsor sponsor = new MyClientSponsor();
        lease.Register(sponsor);

        Console.WriteLine("Client-activated object: " + obj.RemoteMethod());
        Console.WriteLine("Press Enter to end the client application domain.");
        Console.ReadLine();
    }
}

public class MyClientSponsor : MarshalByRefObject, ISponsor
{
    private DateTime lastRenewal;

    public MyClientSponsor()
    {
        Console.WriteLine("MyClientSponsor.ctor called");
        lastRenewal = DateTime.Now;
    }

    public TimeSpan Renewal(ILease lease)
    {
        Console.WriteLine("I've been asked to renew the lease.");
        Console.WriteLine("Time since last renewal:" + (DateTime.Now - lastRenewal).ToString());

        lastRenewal = DateTime.Now;
        return TimeSpan.FromSeconds(20);
    }
}
Imports System
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Lifetime
Imports RemoteType

Class Client

    Shared Sub Main()
        RemotingConfiguration.Configure("Client.exe.config", False)
        Dim obj As ClientActivatedType = New ClientActivatedType()

        Dim lease As ILease = CType(obj.GetLifetimeService(), ILease)
        Dim sponsor As MyClientSponsor = New MyClientSponsor()
        lease.Register(sponsor)

        Console.WriteLine("Client-activated object: " + obj.RemoteMethod())
        Console.WriteLine("Press Enter to end the client application domain.")
        Console.ReadLine()
    End Sub

End Class

Public Class MyClientSponsor
    Inherits MarshalByRefObject
    Implements ISponsor

    Dim lastRenewal As DateTime

    Public Sub New()
        lastRenewal = DateTime.Now
    End Sub

    Public Function Renewal(ByVal lease As System.Runtime.Remoting.Lifetime.ILease) As System.TimeSpan Implements System.Runtime.Remoting.Lifetime.ISponsor.Renewal
        Console.WriteLine("I've been asked to renew the lease.")
        Console.WriteLine("Time since last renewal:" + (DateTime.Now - lastRenewal).ToString())

        lastRenewal = DateTime.Now
        Return TimeSpan.FromSeconds(20)
    End Function
End Class

Client.exe.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.runtime.remoting>
    <application>
      <channels>
        <channel ref="tcp" port="0">
          <clientProviders>
            <formatter ref="binary"/>
          </clientProviders>
          <serverProviders>
            <formatter ref="binary" typeFilterLevel="Full"/>
          </serverProviders>
        </channel>
      </channels>
      <client url="tcp://localhost:1234">
        <activated type="RemoteType.ClientActivatedType, RemoteType" />
      </client>
    </application>
  </system.runtime.remoting>
</configuration>

另请参见

其他资源

远程处理示例
对象激活和生存期