分类目录

链接

2011 年 12 月
 1234
567891011
12131415161718
19202122232425
262728293031  

近期文章

热门标签

新人福利,免费薅羊毛

现在位置:    首页 > .NET > 正文
.NET Remoting系列之远程对象
.NET 暂无评论 阅读(2,532)

在分布系统中,远程对象需要跨越应用程序域进行传递,因此其表示方式会有所不同。基于性能和数据共享等原因考虑,Remoting远程对象可以是 "值封送对象(MBV)" 或 "引用封送对象(MBR)"。

MBV 机制类似于 Web 无状态请求,服务器创建对象实例传递给信道发送到客户端,而后服务器端不再继续维护其状态和生存期。而 MBR 则在其生存期内一直存活在服务器程序域中,客户端只是通过代理对象来完成调用消息传递,客户端可以通过相关接口来延长远程对象的生存期。

实现 MBV 一般通过 SerializableAttribute 特性,或者实现 ISerializable 接口。运行下面的例子,我们会发现远程对象在客户端程序域内,并且不是代理对象。

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Reflection;
  5. using System.Runtime.Serialization;
  6. using System.Runtime.Serialization.Formatters;
  7. using System.Runtime.Serialization.Formatters.Binary;
  8. using System.Runtime.CompilerServices;
  9. using System.Runtime.Remoting;
  10. using System.Runtime.Remoting.Channels;
  11. using System.Runtime.Remoting.Channels.Tcp;
  12. using System.Runtime.Remoting.Messaging;
  13.  
  14. namespace Learn.Library.Remoting
  15. {
  16.     public class RemotingTest2
  17.     {
  18.         /// <summary>
  19.         /// 远程类型
  20.         /// </summary>
  21.         [Serializable]
  22.         public class Data
  23.         {
  24.             private int i;
  25.  
  26.             public int I
  27.             {
  28.                 get { return i; }
  29.                 set { i = value; }
  30.             }
  31.  
  32.             public void Where()
  33.             {
  34.                 Console.WriteLine("{0} in {1}", this.GetType().Name, AppDomain.CurrentDomain.FriendlyName);
  35.             }
  36.         }
  37.  
  38.         /// <summary>
  39.         /// 服务器端代码
  40.         /// </summary>
  41.         static void Server()
  42.         {
  43.             // 创建新的应用程序域,以便模拟分布结构。
  44.             AppDomain server = AppDomain.CreateDomain("server");
  45.             server.DoCallBack(delegate
  46.             {
  47.                 // 创建并注册信道
  48.                 TcpServerChannel channel = new TcpServerChannel(801);
  49.                 ChannelServices.RegisterChannel(channel, false);
  50.  
  51.                 // 注册远程类型
  52.                 RemotingConfiguration.ApplicationName = "test";
  53.                 RemotingConfiguration.RegisterActivatedServiceType(typeof(Data));
  54.             });
  55.         }
  56.  
  57.         /// <summary>
  58.         /// 客户端代码
  59.         /// </summary>
  60.         static void Client()
  61.         {
  62.             // 创建并注册信道
  63.             TcpClientChannel channel = new TcpClientChannel();
  64.             ChannelServices.RegisterChannel(channel, false);
  65.  
  66.             // 注册远程类型
  67.             RemotingConfiguration.RegisterActivatedClientType(typeof(Data), "tcp://localhost:801/test");
  68.  
  69.             // 创建远程对象并调用其方法
  70.             Data data = Activator.CreateInstance(typeof(Data)) as Data;
  71.             data.Where();
  72.  
  73.             // 判断是否是代理
  74.             Console.WriteLine(RemotingServices.IsTransparentProxy(data));
  75.         }
  76.  
  77.         static void Main()
  78.         {
  79.             Server();
  80.             Client();
  81.         }
  82.     }
  83. }

输出:
Data in Learn.CUI.vshost.exe
False

MBR 则要求继承自 MarshalByRefObject 或 ContextBoundObject。继承自 ContextBoundObject 的远程对象,可以包含其执行上下文,比如事务等等,其性能不如 MarshalByRefObject。下面的例子中,远程对象依旧在服务器程序域内执行,客户端只是一个代理对象在转发调用。

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Reflection;
  5. using System.Runtime.Serialization;
  6. using System.Runtime.Serialization.Formatters;
  7. using System.Runtime.Serialization.Formatters.Binary;
  8. using System.Runtime.CompilerServices;
  9. using System.Runtime.Remoting;
  10. using System.Runtime.Remoting.Channels;
  11. using System.Runtime.Remoting.Channels.Tcp;
  12. using System.Runtime.Remoting.Messaging;
  13.  
  14. namespace Learn.Library.Remoting
  15. {
  16.     public class RemotingTest2
  17.     {
  18.         /// <summary>
  19.         /// 远程类型
  20.         /// </summary>
  21.         public class Data : MarshalByRefObject
  22.         {
  23.             private int i;
  24.  
  25.             public int I
  26.             {
  27.                 get { return i; }
  28.                 set { i = value; }
  29.             }
  30.  
  31.             public void Where()
  32.             {
  33.                 Console.WriteLine("{0} in {1}", this.GetType().Name, AppDomain.CurrentDomain.FriendlyName);
  34.             }
  35.         }
  36.  
  37.         /// <summary>
  38.         /// 服务器端代码
  39.         /// </summary>
  40.         static void Server()
  41.         {
  42.             // 创建新的应用程序域,以便模拟分布结构。
  43.             AppDomain server = AppDomain.CreateDomain("server");
  44.             server.DoCallBack(delegate
  45.             {
  46.                 // 创建并注册信道
  47.                 TcpServerChannel channel = new TcpServerChannel(801);
  48.                 ChannelServices.RegisterChannel(channel, false);
  49.  
  50.                 // 注册远程类型
  51.                 RemotingConfiguration.RegisterWellKnownServiceType(typeof(Data), "data",
  52.                     WellKnownObjectMode.Singleton);
  53.             });
  54.         }
  55.  
  56.         /// <summary>
  57.         /// 客户端代码
  58.         /// </summary>
  59.         static void Client()
  60.         {
  61.             // 创建并注册信道
  62.             TcpClientChannel channel = new TcpClientChannel();
  63.             ChannelServices.RegisterChannel(channel, false);
  64.  
  65.             // 创建远程对象并调用其方法
  66.             Data data = (Data)Activator.GetObject(typeof(Data), "tcp://localhost:801/data");
  67.             data.Where();
  68.  
  69.             // 判断是否是代理
  70.             Console.WriteLine(RemotingServices.IsTransparentProxy(data));
  71.         }
  72.  
  73.         static void Main()
  74.         {
  75.             Server();
  76.             Client();
  77.         }
  78.     }
  79. }

输出:
Data in server
True

MBV 传递完整的副本到客户端,而后的所有调用都是在客户端程序域内进行,不再需要跨域的往返过程。但完整复制和序列化需要更多的资源和往返时间,因此不适合较大的对象,同时无法在多个客户端间共享信息。而 MBR 的所有调用都是通过代理进行的,因此往返过程比较多,但因执行过程都在服务器端进行,其整体性能还是非常高的。在系统设计时可以针对不同的应用采取不同的选择。

============ 欢迎各位老板打赏~ ===========

本文版权归Bruce's Blog所有,转载引用请完整注明以下信息:
本文作者:Bruce
本文地址:.NET Remoting系列之远程对象 | Bruce's Blog

发表评论

留言无头像?