[Remoting] 三:激活模式(收藏转帖http://www.rainsts.net/article.asp?id=410)
来源:互联网 发布:网速实时监控软件 编辑:程序博客网 时间:2024/05/16 16:06
对于 MBR,我们可以指定不同的激活模式。
在 Remoting 中,我们使用 RemotingConfiguration 类型来完成远程类型的注册。RegisterWellKnownServiceType()、RegisterWellKnownClientType() 用于注册服务器激活对象,通过 WellKnownObjectMode 枚举参数可以指定 Singleton 或 SingleCall 模式。RegisterActivatedServiceType()、RegisterActivatedClientType() 用于注册客户端激活对象。
注册方式演示
1. SAO / Singleton
2. SAO / SingleCall
3. CAO
由于 RegisterActivatedServiceType 中不能为远程对象指定 URI,因此我们需要使用 ApplicationName 属性。
创建时间的区别
我们在远程对象创建和方法调用代码之间进行一些延时来观察创建时间的异同。
1. 服务器激活
输出:
2007-2-23 14:22:06
2007-2-23 14:22:06
输出结果表明,对象在方法调用时才被创建。
2. 客户端激活
输出:
2007-2-23 14:25:07
2007-2-23 14:25:10
输出结果证实远程对象在执行 new 语句时被创建。
Singleton 和 SingleCall 的区别
Singleton
输出:
94cc586b-a24f-4633-9c88-c98a93246453
94cc586b-a24f-4633-9c88-c98a93246453
两个不同的代理对象引用了同一个远程对象,符合 Singleton 的定义。
SingleCall
输出:
6141870b-43db-4d2f-a991-73ae4097ffd3
8e28bf26-5aab-4975-a36a-da61a4bcb93e
即便是同一个代理对象,也会为每次方法调用创建一个新的远程对象。
- 服务器激活(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");
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");
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); // 可以使用非默认构造方法
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();
}
}
}
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();
}
}
}
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();
}
}
}
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();
}
}
}
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] 三:激活模式(收藏转帖http://www.rainsts.net/article.asp?id=410)
- [Remoting] 五:信道(收藏转帖http://www.rainsts.net/article.asp?id=412)
- [Remoting] 十一:事件(收藏转帖http://www.rainsts.net/article.asp?id=419)
- [Remoting] 十二:配置文件(收藏转帖http://www.rainsts.net/article.asp?id=420)
- NET Remoting一,二(收藏转帖http://www.rainsts.net/article.asp?id=408)
- [Remoting] 四:生存期租约(收藏转帖http://www.rainsts.net/article.asp?id=411)
- [Remoting] 六:异步调用(收藏转帖http://www.rainsts.net/article.asp?id=413)
- [Remoting] 七:调用上下文(收藏转帖http://www.rainsts.net/article.asp?id=414)
- [Remoting] 八:元数据(收藏转帖http://www.rainsts.net/article.asp?id=415)
- [Remoting] 九:动态发布(收藏转帖http://www.rainsts.net/article.asp?id=416)
- [Remoting] 十:追踪服务(收藏转帖http://www.rainsts.net/article.asp?id=417)
- Message Queuing(收藏转帖http://www.rainsts.net/article.asp?id=418)
- 动态调用 WebService (收藏转贴http://www.rainsts.net/article.asp?id=304)
- [ASP.NET 优化] IIS6 Gziphttp://www.rainsts.net/article.asp?id=531
- 从雨痕老大的博客上转来的 http://www.rainsts.net/article.asp?id=1066 读书人偷书不算窃 :)
- asp.net控件开发基础 来源:http://www.clingingboy.com/blog/article.asp?id=258
- [Remoting] 三:激活模式
- WebConfirm控件(转自http://www.evget.com/view/article/viewArticle.asp?article=961)
- 不地道的,令人生厌的
- 最基本的Socket编程 C#版 [转]
- 共享(独享)IP动态(静态)IP固定IP?
- spcomm
- 史上十大最笨网上创业点子但全都获得成功
- [Remoting] 三:激活模式(收藏转帖http://www.rainsts.net/article.asp?id=410)
- 美文欣赏-------小石潭记
- 如何使用RSS让它融入你的生活
- Visual C#.Net 网络程序开发-Socket篇
- [Remoting] 四:生存期租约(收藏转帖http://www.rainsts.net/article.asp?id=411)
- web service
- [精华] 网络socket编程指南
- [Remoting] 五:信道(收藏转帖http://www.rainsts.net/article.asp?id=412)
- 选鼠标的禁忌即6大误区