.Net Remoting 技术是.NET平台上实现分布式对象系统的框架,它可以用于访问另一个应用程序域(也可以是另一个服务器)中的对象,可以是进程间的,也可以是不同系统的进程间,这种CS式的通讯机制更为快速方便。
其实质就是:客户端创建服务端对象的代理并调用其方法,通过信道网络传输到服务端,在服务端上处理客户端传递过来的参数数据并返回处理结果(如果有的话)给客户端的接收变量。这种方式与传统上的方法调用明显不同,它轻松实现了数据的分布式处理
Remoting的应用一般由三部分构成,远程类,服务端、客户端。其中服务端和客户端都要引入远程类,在整个应用中远程类相当于一个传输数据的载体,并且所有的远程类必须继承自System.MarshalByRefObject,客户端相当于调用方,服务端相当于执行方。
基本的操作流程如下:
1、创建服务程序集(ServerAssembly) | |
2、创建宿主应用程序(服务器端ServerConsole) | |
2、1、注册通道 IChannelReceiver tcpChnl = newTcpChannel(8501); ChannelServices.RegisterChannel(tcpChnl, false); | |
2、2、注册实例RemotingConfiguration.RegisterActivatedServiceType(t); | |
3、客户端应用程序(ClientControl) | |
3、1、册客户激活对象 string url = "tcp://127.0.0.1:8501"; | |
4.程序运行测试 | |
4、1、服务端 RegisterChannel(); // 注册通道 | |
4、2、客户端 ClientActivated(); // 客户激活方式 | |
具体的Demo如下(参考自博客园Jimmy Zhang)
1、创建服务程序集(ServerAssembly)
{
publicclassDemoClass:MarshalByRefObject {
privateint count = 0;
public DemoClass() {
Console.WriteLine(" ======= DomoClass Constructor =======");
}
publicvoid ShowCount(string name) {
count++;
Console.WriteLine("{0},the count is {1}.", name, count);
}
// 打印对象所在的应用程序域
publicvoid ShowAppDomain() {
AppDomain currentDomain = AppDomain.CurrentDomain;
Console.WriteLine(currentDomain.FriendlyName);
}
publicint GetCount() {
return count;}}
}
2、创建宿主应用程序(服务器端ServerConsole)
{
1、注册通道
privatestaticvoid RegisterChannel() {
// 创建通道实例
// IChannel tcpChnl = newTcpChannel(8501);
IChannelReceiver tcpChnl = newTcpChannel(8501);
// 注册tcp通道
ChannelServices.RegisterChannel(tcpChnl, false);
// 注册http通道
IChannel httpChnl = newHttpChannel(8502);
ChannelServices.RegisterChannel(httpChnl, false);
}
2、注册实例
客户激活对象的注册方式需要使用RemotingConfiguration类型的RegisterActivatedServiceType()静态方法:
// 注册 客户激活对象 Client Activated Object
privatestaticvoid ClientActivated() {
Console.WriteLine("方式: Client Activated Object");
Type t = typeof(DemoClass);
RemotingConfiguration.RegisterActivatedServiceType(t);
}
服务激活对象 可以使用RemotingConfiguration类型的 RegisterWellKnownServiceType()静态方法:
// 注册 服务激活对象 SingleCall
privatestaticvoid ServerActivatedSingleCall() {
Console.WriteLine("方式: Server Activated SingleCall");
Type t = typeof(DemoClass);
RemotingConfiguration.RegisterWellKnownServiceType(
t, "ServerActivated", WellKnownObjectMode.SingleCall);
}
// 注册 服务端激活对象 Singleton
privatestaticvoid ServerActivatedSingleton() {
Console.WriteLine("方式: Server Activated Singleton");
Type t = typeof(DemoClass);
RemotingConfiguration.RegisterWellKnownServiceType(
t, "ServerActivated", WellKnownObjectMode.Singleton);
}
}
3、客户端应用程序(ClientControl)
// 注册客户激活对象
privatestaticvoid ClientActivated() {
Type t = typeof(DemoClass);
// 下面两个 url 任选一个
string url = "tcp://127.0.0.1:8501";
//string url = "tcp://127.0.0.1:8501/SimpleRemote";
RemotingConfiguration.RegisterActivatedClientType(t, url);
}
// 注册服务激活对象
privatestaticvoid ServerActivated() {
Type t = typeof(DemoClass);
string url = "tcp://127.0.0.1:8501/SimpleRemote/ServerActivated";
RemotingConfiguration.RegisterWellKnownClientType(t, url);
}
4、运行测试
客户端激活模式
客户激活方式
服务端的Main()代码如下:
staticvoid(string[] args) {
RegisterChannel(); // 注册通道
ClientActivated(); // 客户激活方式
Console.WriteLine("服务开启,可按任意键退出... ");
Console.ReadKey();
}
客户端的Main()代码如下:
static void (string[] args) {
// 注册远程对象
ClientActivated(); // 客户激活方式
RunTest("Jimmy", "Zhang");
RunTest("Bruce", "Wang");
Console.WriteLine("客户端运行结束,按任意键退出...");
Console.ReadKey();
}
private static void RunTest(string firstName, string familyName) {
DemoClass obj = newDemoClass();
obj.ShowAppDomain();
obj.ShowCount(firstName);
Console.WriteLine("{0}, the count is {1}. ",firstName, obj.GetCount());
obj.ShowCount(familyName);
Console.WriteLine("{0}, the count is {1}.",familyName, obj.GetCount());
}
得到的结论:
- 管是对象的创建,还是对象方法的执行,都在服务端(远程)执行。
- 服务端为每一个客户端(两次RunTest()调用,各创建了一个对象)创建其专属的对象,为这个客户提供服务,并且保存状态(第二次调用ShowCount()的值基于第一次调用ShowCount()之后count的值)。
- 可以从远程获取到方法执行的返回值。(客户端从GetCount()方法获得了返回值)
- 使用客户激活方式时,远程对象在调用new操作时创建
2使用SingleTon模式调用
只需要在客户端将Main函数中ClientActivated();换成 ServerActivatedSingleton()或者ServerActivatedSingleCall();即可,
当使用Singleton模式时,服务端在第一次请求时创建一个对象(构造函数只调用了一次)。对于后继的请求仅使用这个对象进行服务(即使再次调用构造函数也不会创建对象),同时多个客户端共享同一个对象的状态(ShowCount()的值累加)。
对于SingleCall方式来说,对象对每一次方法调用提供服务,换言之,对于每一次方法调用,创建一个全新的对象为其服务,在方法执行完毕后销毁对象