`
leonardleonard
  • 浏览: 821574 次
社区版块
存档分类
最新评论

[Remoting] 三:激活模式

阅读更多
对于 MBR,我们可以指定不同的激活模式。
  • 服务器激活(Server-Activated Objects / SAO):只有在客户端调用代理对象第一个方法时才创建,区分为 Singleton 和 SingleCall 两种模式。Singleton 一如设计模式中的名称,无论有多少客户端都只有一个实例存在;而 SingleCall 则为每次调用创建一个新对象,因此它是无状态的。SingleCall 在方法调用完成后立即失效,不会参与生存期租约系统。
  • 客户端激活(Client-Activated Objects / CAO):在客户端调用 new 或 Activator.CreateInstance 时立即创建。
通常情况下服务器激活模式只能使用默认构造函数,客户端激活模式则没有此限制。当然,可以通过其他方法来绕开这个限制,比如动态发布,我们会在后面的章节解决这个问题。

在 Remoting 中,我们使用 RemotingConfiguration 类型来完成远程类型的注册。RegisterWellKnownServiceType()、RegisterWellKnownClientType() 用于注册服务器激活对象,通过 WellKnownObjectMode 枚举参数可以指定 Singleton 或 SingleCall 模式。RegisterActivatedServiceType()、RegisterActivatedClientType() 用于注册客户端激活对象。

注册方式演示

1. SAO / Singleton
// Server
RemotingConfiguration.RegisterWellKnownServiceType(typeof(Data), "data", WellKnownObjectMode.Singleton);

...

// Client1
RemotingConfiguration.RegisterWellKnownClientType(typeof(Data), "tcp://localhost:801/data");
Data data = new Data(); // 必须使用默认构造方法。

...

// Client2
Data data = (Data)Activator.GetObject(typeof(Data), "tcp://localhost:801/data");

2. SAO / SingleCall
// Server
RemotingConfiguration.RegisterWellKnownServiceType(typeof(Data), "data", WellKnownObjectMode.SingleCall);

...

// Client1
RemotingConfiguration.RegisterWellKnownClientType(typeof(Data), "tcp://localhost:801/data");
Data data = new Data(); // 必须使用默认构造方法。

...

// Client2
Data data = (Data)Activator.GetObject(typeof(Data), "tcp://localhost:801/data");

3. CAO

由于 RegisterActivatedServiceType 中不能为远程对象指定 URI,因此我们需要使用 ApplicationName 属性。
// Server
RemotingConfiguration.ApplicationName = "test"; //
RemotingConfiguration.RegisterActivatedServiceType(typeof(Data));

...

// Client1
RemotingConfiguration.RegisterActivatedClientType(typeof(Data), "tcp://localhost:801/test");
Data data = new Data(123); // 可以使用非默认构造方法

...

// Client2
RemotingConfiguration.RegisterActivatedClientType(typeof(Data), "tcp://localhost:801/test");
Data data = (Data)Activator.CreateInstance(typeof(Data), 123); // 可以使用非默认构造方法

创建时间的区别

我们在远程对象创建和方法调用代码之间进行一些延时来观察创建时间的异同。

1. 服务器激活
using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.CompilerServices;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Messaging;

namespace Learn.Library.Remoting
{
  public class RemotingTest2
  {
    /// <summary>
    /// 远程类型
    /// </summary>
    public class Data : MarshalByRefObject
    {
      public Data()
      {
        Console.WriteLine(DateTime.Now);
      }

      public void Test()
      {
        Console.WriteLine(DateTime.Now);
      }
    }

    /// <summary>
    /// 服务器端代码
    /// </summary>
    static void Server()
    {
      // 创建新的应用程序域,以便模拟分布结构。
      AppDomain server = AppDomain.CreateDomain("server");
      server.DoCallBack(delegate
      {
        // 创建并注册信道
        TcpServerChannel channel = new TcpServerChannel(801);
        ChannelServices.RegisterChannel(channel, false);

        // 注册远程类型
        RemotingConfiguration.RegisterWellKnownServiceType(typeof(Data), "data",
          WellKnownObjectMode.SingleCall);
      });
    }

    /// <summary>
    /// 客户端代码
    /// </summary>
    static void Client()
    {
      // 创建并注册信道
      TcpClientChannel channel = new TcpClientChannel();
      ChannelServices.RegisterChannel(channel, false);

      // 创建远程对象并调用其方法
      Data data = (Data)Activator.GetObject(typeof(Data), "tcp://localhost:801/data");
      Thread.Sleep(3000);
      data.Test();
    }

    static void Main()
    {
      Server();
      Client();
    }
  }
}

输出:
2007-2-23 14:22:06
2007-2-23 14:22:06

输出结果表明,对象在方法调用时才被创建。

2. 客户端激活
using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.CompilerServices;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Messaging;

namespace Learn.Library.Remoting
{
  public class RemotingTest2
  {
    /// <summary>
    /// 远程类型
    /// </summary>
    public class Data : MarshalByRefObject
    {
      public Data()
      {
        Console.WriteLine(DateTime.Now);
      }

      public void Test()
      {
        Console.WriteLine(DateTime.Now);
      }
    }

    /// <summary>
    /// 服务器端代码
    /// </summary>
    static void Server()
    {
      // 创建新的应用程序域,以便模拟分布结构。
      AppDomain server = AppDomain.CreateDomain("server");
      server.DoCallBack(delegate
      {
        // 创建并注册信道
        TcpServerChannel channel = new TcpServerChannel(801);
        ChannelServices.RegisterChannel(channel, false);

        // 注册远程类型
        RemotingConfiguration.ApplicationName = "test";
        RemotingConfiguration.RegisterActivatedServiceType(typeof(Data));
      });
    }

    /// <summary>
    /// 客户端代码
    /// </summary>
    static void Client()
    {
      // 创建并注册信道
      TcpClientChannel channel = new TcpClientChannel();
      ChannelServices.RegisterChannel(channel, false);

      // 创建远程对象并调用其方法
      RemotingConfiguration.RegisterActivatedClientType(typeof(Data), "tcp://localhost:801/test");
      Data data = new Data();
      Thread.Sleep(3000);
      data.Test();
    }

    static void Main()
    {
      Server();
      Client();
    }
  }
}

输出:
2007-2-23 14:25:07
2007-2-23 14:25:10

输出结果证实远程对象在执行 new 语句时被创建。

Singleton 和 SingleCall 的区别

Singleton
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.CompilerServices;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Messaging;

namespace Learn.Library.Remoting
{
  public class RemotingTest2
  {
    /// <summary>
    /// 远程类型
    /// </summary>
    public class Data : MarshalByRefObject
    {
      private Guid id = Guid.NewGuid();

      public void Test()
      {
        Console.WriteLine(id.ToString());
      }
    }

    /// <summary>
    /// 服务器端代码
    /// </summary>
    static void Server()
    {
      // 创建新的应用程序域,以便模拟分布结构。
      AppDomain server = AppDomain.CreateDomain("server");
      server.DoCallBack(delegate
      {
        // 创建并注册信道
        TcpServerChannel channel = new TcpServerChannel(801);
        ChannelServices.RegisterChannel(channel, false);

        // 注册远程类型
        RemotingConfiguration.RegisterWellKnownServiceType(typeof(Data), "data",
          WellKnownObjectMode.Singleton);
      });
    }

    /// <summary>
    /// 客户端代码
    /// </summary>
    static void Client()
    {
      // 创建并注册信道
      TcpClientChannel channel = new TcpClientChannel();
      ChannelServices.RegisterChannel(channel, false);

      // 注册远程对象
      RemotingConfiguration.RegisterWellKnownClientType(typeof(Data), "tcp://localhost:801/data");

      // 创建远程对象并调用其方法
      Data data1 = new Data();
      Data data2 = new Data();

      data1.Test();
      data2.Test();
    }

    static void Main()
    {
      Server();
      Client();
    }
  }
}

输出:
94cc586b-a24f-4633-9c88-c98a93246453
94cc586b-a24f-4633-9c88-c98a93246453

两个不同的代理对象引用了同一个远程对象,符合 Singleton 的定义。

SingleCall
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.CompilerServices;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Messaging;

namespace Learn.Library.Remoting
{
  public class RemotingTest2
  {
    /// <summary>
    /// 远程类型
    /// </summary>
    public class Data : MarshalByRefObject
    {
      private Guid id = Guid.NewGuid();

      public void Test()
      {
        Console.WriteLine(id.ToString());
      }
    }

    /// <summary>
    /// 服务器端代码
    /// </summary>
    static void Server()
    {
      // 创建新的应用程序域,以便模拟分布结构。
      AppDomain server = AppDomain.CreateDomain("server");
      server.DoCallBack(delegate
      {
        // 创建并注册信道
        TcpServerChannel channel = new TcpServerChannel(801);
        ChannelServices.RegisterChannel(channel, false);

        // 注册远程类型
        RemotingConfiguration.RegisterWellKnownServiceType(typeof(Data), "data",
          WellKnownObjectMode.SingleCall);
      });
    }

    /// <summary>
    /// 客户端代码
    /// </summary>
    static void Client()
    {
      // 创建并注册信道
      TcpClientChannel channel = new TcpClientChannel();
      ChannelServices.RegisterChannel(channel, false);

      // 创建远程对象并调用其方法
      Data data = (Data)Activator.GetObject(typeof(Data), "tcp://localhost:801/data");

      data.Test();
      data.Test();
    }

    static void Main()
    {
      Server();
      Client();
    }
  }
}

输出:
6141870b-43db-4d2f-a991-73ae4097ffd3
8e28bf26-5aab-4975-a36a-da61a4bcb93e

即便是同一个代理对象,也会为每次方法调用创建一个新的远程对象。  
 
分享到:
评论

相关推荐

    remoting三层架构C#实例原码

    在软件开发中,三层架构是一种常见的设计模式,它将应用程序分为三个主要部分:表现层(Presentation Layer)、业务逻辑层(Business Logic Layer)和数据访问层(Data Access Layer)。表现层负责用户交互,业务...

    Microsoft .Net Remoting系列专题之三:Remoting事件处理全接触

    在Remoting中处理事件涉及以下三个方面: 1. **服务端订阅客户端事件**:在这种模式下,客户端作为事件的源,服务端作为事件的订阅者。客户端触发事件,服务端通过监听和响应这些事件来执行相应操作。这种场景常...

    remoting三层架构项目源码

    三层架构是一种常见的软件设计模式,用于分离应用程序的不同职责,提高可维护性和可扩展性。这三层包括: - **表示层(Presentation Layer)**:负责用户界面,处理用户输入,显示结果。在Web应用程序中,通常对应...

    .NET Remoting学习笔记

    - 在客户端激活模式下,客户端负责创建远程对象的实例,并通过 Remoting 将这个实例传递给服务器。这种方式适用于需要更多控制权的场景。 #### 三、信道 .NET Remoting 支持多种通信信道,其中最常用的是 ...

    Microsoft .Net Remoting系列专题

    这种激活方式又细分为两种模式: 1. SingleTon模式:在这种模式下,无论有多少个客户端请求,都会共享同一个对象实例。这意味着对象的状态在整个生命周期内保持,适合于需要共享状态的场景。 2. SingleCall模式:每...

    VB_NET Remoting 高级技术手册

    1. 对象激活:Remoting支持两种激活模式,即单向激活(Server Activated)和双向激活(Client Activated)。在单向激活中,服务器创建对象并准备好供客户端使用;而在双向激活中,客户端请求创建服务器端的对象。 2...

    深度挖掘.NET Framework 2.0(8):实战.NET Remoting(下)

    Remoting还支持两种对象模式:单向和双向通信。 三、激活模式 1. **Singleton**:确保在整个系统中只有一个实例存在,常用于全局服务。 2. **Singleton激活**:无论何时何地,客户端请求的都是同一个对象实例。 3. ...

    Remoting测试资源

    有两种激活模式:单向激活(Singleton)和多实例激活(Singleton)。单向激活确保整个应用程序生命周期中只有一个对象实例,而多实例激活则每次请求都会创建新的对象。 2. **通道**: 通道是Remoting的通信机制,...

    Remoting双向通信V4.0.rar

    2. **激活模式**:Remoting支持两种激活模式——远程激活(Remote Activation)和自激活(Self-Activation)。远程激活时,客户端请求服务器创建一个对象实例;自激活时,对象可以在客户端或服务器上自行创建,然后...

    remoting服务

    此外,Remoting支持两种主要的激活模式:服务器激活和客户端激活。服务器激活是由服务器端创建并管理对象,客户端只需要引用;客户端激活则是由客户端请求时创建对象,提高了灵活性。 接口在Remoting中扮演着关键...

    Remoting经典样例(含完整项目代码)

    4. **对象生存期管理(Object Lifetime Management)**:.NET Remoting提供了多种策略来管理远程对象的生命周期,包括Singleton(单例模式)、PerCall(每次调用创建新实例)和Lease(租约)管理。 5. **远程对象...

    Remoting双向通信例程

    2. **激活模式**:有两种激活模式,即“远程激活”(Remote Activation)和“自激活”(Self-Activation)。远程激活需要服务器先启动,然后客户端请求服务对象;而自激活则允许客户端创建服务对象实例。 3. **接口...

    remoting实例

    10. **设计模式应用**:在分布式环境中,往往采用工厂模式、代理模式等设计模式来简化对象的创建和访问过程。 在这个"Remoting实例二"的项目中,我们可以进一步学习如何实际操作这些概念,包括创建服务端接口和实现...

    Remoting双向通信V2.0.rar

    Remoting的核心概念包括激活模式、通道和服务端与客户端。激活模式分为两种:服务器激活和客户端激活。服务器激活是由服务器创建对象实例,然后将实例的引用传递给客户端;客户端激活则是由客户端创建对象实例,实例...

    Remoting开发示例

    8. **实例化策略**:Remoting支持单例模式、多例模式等多种实例化策略,根据应用场景选择合适的策略,可以提高系统效率和资源利用率。 9. **跨平台兼容性**:虽然Remoting主要设计用于.NET环境,但通过使用Mono等...

    .Net Remoting系列(6)

    1. **激活模式**:Remoting支持两种对象激活模式——远程激活(Remote Activation,即服务器端创建对象)和本地激活(Local Activation,客户端创建对象)。远程激活模式下,对象在服务器端创建并管理,客户端只获取...

    .NET Remoting

    4. **激活模式**:Remoting支持两种激活模式:Singleton(单例)和Well-Known Object(知名对象)。Singleton模式保证同一时间只有一个实例存在,而Well-Known Object可以创建多个实例。 5. **序列化和反序列化**:...

    remoting双向通讯

    3. **激活模式**:Remoting对象有两种激活模式: Singleton(单例)和Transient(瞬时)。Singleton模式保证任何时候只有一个实例存在,而Transient模式每次请求都会创建新的实例。 4. **AppDomain**:AppDomain是...

    VB.NET Remoting 技术手册

    3. SingletonWithPooling模式:在服务器端维护一个对象池,为客户端提供对象实例。 五、Remoting安全性 Remoting提供了多种安全特性,如权限控制、身份验证和加密。开发者可以通过配置安全策略来限制对远程对象的...

Global site tag (gtag.js) - Google Analytics