爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      .net remoting 技术

      首页 知识中心 云端实践 文章详情页

      .net remoting 技术

      2023-07-24 09:39:37 阅读次数:425

      客户端,对象,远程

      .net remoting 技术

      1简介

      什么是Remoting,简而言之,我们可以将其看作是一种分布式处理方式
       
      。从微软的产品角度来看,可以说Remoting就是DCOM的一种升级,它改善了很多功能,并极好的融合到.Net平台下。Microsoft .NET Remoting 提供了一种允许对象通过应用程序域与另一对象进行交互的框架。这也正是我们使用Remoting的原因。为什么呢?在Windows操作系统中,是将应用程序分离为单独的进程。这个进程形成了应用程序代码和数据周围的一道边界。如果不采用进程间通信(RPC)机制,则在一个进程中执行的代码就不能访问另一进程。这是一种操作系统对应用程序的保护机制。然而在某些情况下,我们需要跨过应用程序域,与另外的应用程序域进行通信,即穿越边界。
      在Remoting中是通过通道(channel)来实现两个应用程序域之间对象的通信的。首先,客户端通过Remoting,访问通道以获得服务端对象,再通过代理解析为客户端对象。这就提供一种可能性,即以服务的方式来发布服务器对象。远程对象代码可以运行在服务器上(如服务器激活的对象和客户端激活的对象),然后客户端再通过Remoting连接服务器,获得该服务对象并通过序列化在客户端运行。
      在Remoting中,对于要传递的对象,设计者除了需要了解通道的类型和端口号之外,无需再了解数据包的格式。这既保证了客户端和服务器端有关对象的松散耦合,同时也优化了通信的性能。

      2主要元素

      ● 远程对象——远程对象是运行在服务器上的对象。客户端不能直接调用远程对象上的方法,而要使用代理。使用.NET,很容易把远程对象和本地对象区分开:即任何派生自 MarshalByRefObject 的类从来都不会离开它的应用程序域。客户端可以通过代理调用远程对象的方法。
      ● 信道——信道用于客户端和服务器之间的通信。信道包括客户端的信道部分和服务器的信道部分。.NET Framework 4 提供了 3 种信道类型,它们分别通过 TCP、HTTP 和IPC 进行通信。此外,还可以创建自定义信道,这些信道使用其他协议通信。
      ● 消息——消息被发送到信道中。消息是为客户端和服务器之间的通信而创建的。消息包含远程对象的信息、被调用方法的名称以及所有的参数。
      ● 格式化程序——格式化程序用于定义消息如何传输到信道中。.NET 4 有SOAP 格式化程序和二进制格式化程序。使用 SOAP 格式化程序可以与不是基于.NET Framework 的Web 服务通信。二进制格式化程序速度更快,可以有效地用在内部网环境中。当然,也可以创建自定义格式化程序。
      ● 格式化程序提供程序——格式化程序提供程序用于把格式化程序与信道关联起来。通过创建信道,可以指定要使用的格式化程序提供程序,格式化程序提供程序则定义把数据传输到信道中时所使用的格式化程序。
      ● 代理——客户端调用代理的方法,而不是远程对象的方法。代理分为两种:透明的代理和真实的代理。对于客户端,透明代理看起来与远程对象类似。在透明代理上,客户端可以调用远程对象实现的方法。然后,透明代理调用真实代理上的 Invoke()方法。Invoke()方法使用消息接收器把消息传递给信道。
      ● 消息接收器——消息接收器是一个侦听器(interceptor)对象,简称接收器。在客户端和服务器上都有侦听器。接收器与信道相关联。真实的代理使用消息接收器把消息传递到信道中,因此,在消息进入信道之前,接收器可以进行截获工作。根据接收器所处的位置,可以把接收器称为特使接收器(envoy sink)、服务器上下文接收器、对象上下文接收器等。
      ● 激活器——客户端可以使用激活器在服务器上创建远程对象,或者获取一个被服务器激活的对象的代理。
      ● RemotingConfiguration 类——该类是用于配置远程服务器和客户端的一个实用程序类。它可以用于读取配置文件或动态地配置远程对象。
      ● ChannelServices 类——该类是一个实用程序类,可用于注册信道并把消息分配到信道中。[1]

      3两种通道

      Remoting的通道主要有两种:Tcp和Http。在.Net中,System.Runtime.Remoting.Channels中定义了 IChannel接口。IChannel接口包括了TcpChannel通道类型和Http通道类型。它们分别对应Remoting通道的这两种类型。
      TcpChannel类型放在名字空间System.Runtime.Remoting.Channels.Tcp中。Tcp通道提供了基于Socket 的传输工具,使用Tcp协议来跨越Remoting边界传输序列化的消息流。TcpChannel类型默认使用二进制格式序列化消息对象,因此它具有更高的传输性能。HttpChannel类型放在名字空间System.Runtime.Remoting.Channels.Http中。它提供了一种使用 Http协议,使其能在Internet上穿越防火墙传输序列化消息流。默认情况下,HttpChannel类型使用Soap格式序列化消息对象,因此它具有更好的互操作性。通常在局域网内,我们更多地使用TcpChannel;如果要穿越防火墙,则使用HttpChannel。

      4激活方式

      在访问远程类型的一个对象实例之前,必须通过一个名为Activation的进
      .net remoting 技术
      程创建它并进行初始化。这种客户端通过通道来创建远程对象,称为对象的激活。在Remoting中,远程对象的激活分为两大类:服务器端激活和客户端激活。
      服务器端激活,又叫做WellKnow方式,很多又翻译为知名对象。为什么称为知名对象激活模式呢?是因为服务器应用程序在激活对象实例之前会在一个众所周知的统一资源标识符(URI)上来发布这个类型。然后该服务器进程会为此类型配置一个WellKnown对象,并根据指定的端口或地址来发布对象。. Net Remoting把服务器端激活又分为SingleTon模式和SingleCall模式两种。
      SingleTon模式:此为有状态模式。如果设置为SingleTon激活方式,则Remoting将为所有客户端建立同一个对象实例。当对象处于活动状态时, SingleTon实例会处理所有后来的客户端访问请求,而不管它们是同一个客户端,还是其他客户端。SingleTon实例将在方法调用中一直维持其状态。举例来说,如果一个远程对象有一个累加方法(i=0;++i),被多个客户端(例如两个)调用。如果设置为SingleTon方式,则第一个客户获得值为1,第二个客户获得值为2,因为他们获得的对象实例是相同的。如果熟悉Asp .Net的状态管理,我们可以认为它是一种Application状态。
      SingleCall模式:SingleCall是一种无状态模式。一旦设置为SingleCall模式,则当客户端调用远程对象的方法时, Remoting会为每一个客户端建立一个远程对象实例,至于对象实例的销毁则是由GC自动管理的。同上一个例子而言,则访问远程对象的两个客户获得的都是1。我们仍然可以借鉴Asp .Net的状态管理,认为它是一种Session状态。
      客户端激活。与WellKnown模式不同, Remoting在激活每个对象实例的时候,会给每个客户端激活的类型指派一个URI。客户端激活模式一旦获得客户端的请求,将为每一个客户端都建立一个实例引用。SingleCall模式和客户端激活模式是有区别的:首先,对象实例创建的时间不一样。客户端激活方式是客户一旦发出调用的请求,就实例化;而SingleCall则是要等到调用对象方法时再创建。其次,SingleCall模式激活的对象是无状态的,对象生命期的管理是由GC管理的,而客户端激活的对象则有状态,其生命周期可自定义。其三,两种激活模式在服务器端和客户端实现的方法不一样。尤其是在客户端,SingleCall模式是由 GetObject()来激活,它调用对象默认的构造函数。而客户端激活模式,则通过CreateInstance()来激活,它可以传递参数,所以可以调用自定义的构造函数来创建实例。

      5对象定义

      前面讲到,客户端在获取服务器端对象时,并不是获得实际的服务端对象,而是获得它的引用。因此在Remoting中,对于远程对象有一些必须的定义规范要遵循。
      由于Remoting传递的对象是以引用的方式,因此所传递的远程对象类必须继承MarshalByRefObject。MSDN对 MarshalByRefObject的说明是:MarshalByRefObject 是那些通过使用代理交换消息来跨越应用程序域边界进行通信的对象的基类。不是从 MarshalByRefObject 继承的对象会以隐式方式按值封送。当远程应用程序引用一个按值封送的对象时,将跨越远程处理边界传递该对象的副本。因为您希望使用代理方法而不是副本方法进行通信,因此需要继承MarshallByRefObject。
      在Remoting中能够传递的远程对象可以是各种类型,包括复杂的DataSet对象,只要它能够被序列化。远程对象也可以包含事件,但服务器端对于事件的处理比较特殊,我将在本系列之三中介绍。

      6服务器

      根据第一部分所述,根据激活模式的不同,通道类型的不同服务器端的实现方式也有所不同。大体上说,服务器端应分为三步:
      1、注册通道
      要跨越应用程序域进行通信,必须实现通道。如前所述,Remoting提供了IChannel接口,分别包含TcpChannel和HttpChannel两种类型的通道。这两种类型除了性能和序列化数据的格式不同外,实现的方式完全一致,因此下面我们就以TcpChannel为例。
      注册TcpChannel,首先要在项目中添加引用“System.Runtime.Remoting”,然后using名字空间:System.Runtime.Remoting.Channel.Tcp。代码如下:
      TcpChannel channel = new TcpChannel(8080);
      ChannelServices.RegisterChannel(channel);
      在实例化通道对象时,将端口号作为参数传递。然后再调用静态方法RegisterChannel()来注册该通道对象即可。
      2、远程对象
      注册了通道后,要能激活远程对象,必须在通道中注册该对象。根据激活模式的不同,注册对象的方法也不同。
      (1) SingleTon模式
      对于WellKnown对象,可以通过静态方法RemotingConfiguration.RegisterWellKnownServiceType()来实现:RemotingConfiguration.RegisterWellKnownServiceType(
      typeof(ServerRemoteObject.ServerObject),
      "ServiceMessage",WellKnownObjectMode.SingleTon);
      (2)SingleCall模式
      注册对象的方法基本上和SingleTon模式相同,只需要将枚举参数WellKnownObjectMode改为SingleCall就可以了。RemotingConfiguration.RegisterWellKnownServiceType(
      typeof(ServerRemoteObject.ServerObject),
      "ServiceMessage",WellKnownObjectMode.SingleCall);
      (3)激活模式
      对于客户端激活模式,使用的方法又有不同,但区别不大,看了代码就一目了然。
      RemotingConfiguration.ApplicationName = "ServiceMessage";
      RemotingConfiguration.RegisterActivatedServiceType(
      typeof(ServerRemoteObject.ServerObject));
      为什么要在注册对象方法前设置ApplicationName属性呢?其实这个属性就是该对象的URI。对于WellKnown模式,URI是放在RegisterWellKnownServiceType()方法的参数中,当然也可以拿出来专门对ApplicationName属性赋值。而RegisterActivatedServiceType()方法的重载中,没有ApplicationName的参数,所以必须分开。
      3、注销通道
      如果要关闭Remoting的服务,则需要注销通道,也可以关闭对通道的监听。在Remoting中当我们注册通道的时候,就自动开启了通道的监听。而如果关闭了对通道的监听,则该通道就无法接受客户端的请求,但通道仍然存在,如果你想再一次注册该通道,会抛出异常。
      //获得当前已注册的通道;
      IChannel[] channels = ChannelServices.RegisteredChannels;
      //关闭指定名为MyTcp的通道;
      foreach (IChannel eachChannel in channels)
      {
      if (eachChannel.ChannelName == "MyTcp")
      {
      TcpChannel tcpChannel = (TcpChannel)eachChannel;
      //关闭监听;
      tcpChannel.StopListening(null);
      //注销通道;
      ChannelServices.UnregisterChannel(tcpChannel);
      }
      }
      代码中,RegisterdChannel属性获得的是当前已注册的通道。在Remoting中,是允许同时注册多个通道的,这一点会在后面说明。

      7客户

      客户端主要做两件事,一是注册通道。这一点从图一就可以看出,Remoting中服务器端和客户端都必须通过通道来传递消息,以获得远程对象。第二步则是获得该远程对象。
      1、注册通道:
      TcpChannel channel = new TcpChannel();
      ChannelServices.RegisterChannel(channel);
      注意在客户端实例化通道时,是调用的默认构造函数,即没有传递端口号。事实上,这个端口号是缺一不可的,只不过它的指定被放在后面作为了Uri的一部分。
      2、获得远程对象。
      与服务器端相同,不同的激活模式决定了客户端的实现方式也将不同。不过这个区别仅仅是WellKnown激活模式和客户端激活模式之间的区别,而对于SingleTon和SingleCall模式,客户端的实现完全相同。
      (1) WellKnown激活模式
      要获得服务器端的知名远程对象,可通过Activator进程的GetObject()方法来获得:
      ServerRemoteObject.ServerObject serverObj = (ServerRemoteObject.ServerObject)Activator.GetObject(
      typeof(ServerRemoteObject.ServerObject), "tcp://localhost:8080/ServiceMessage");
      首先以WellKnown模式激活,客户端获得对象的方法是使用GetObject()。其中参数第一个是远程对象的类型。第二个参数就是服务器端的uri。如果是http通道,自然是用了。因为我是用本地机,所以这里是localhost,你可以用具体的服务器IP地址来代替它。端口必须和服务器端的端口一致。后面则是服务器定义的远程对象服务名,即ApplicationName属性的内容。
      (2)客户端激活模式
      如前所述,WellKnown模式在客户端创建对象时,只能调用默认的构造函数,上面的代码就说明了这一点,因为GetObject()方法不能传递构造函数的参数。而客户端激活模式则可以通过自定义的构造函数来创建远程对象。
      客户端激活模式有两种方法:
      1) 调用RemotingConfiguration的静态方法RegisterActivatedClientType()。这个方法返回值为Void,它只是将远程对象注册在客户端而已。具体的实例化还需要调用对象类的构造函数。
      RemotingConfiguration.RegisterActivatedClientType(
      typeof(ServerRemoteObject.ServerObject),
      "tcp://localhost:8080/ServiceMessage");
      ServerRemoteObject.ServerObject serverObj = new ServerRemoteObject.ServerObject();
      2) 调用进程Activator的CreateInstance()方法。这个方法将创建方法参数指定类型的类对象。它与前面的GetObject()不同的是,它要在客户端调用构造函数,而GetObject()只是获得对象,而创建实例是在服务器端完成的。CreateInstance()方法有很多个重载,我着重说一下其中常用的两个。
      a、 public static object CreateInstance(Type type, object[] args, object[] activationAttributes);
      参数说明:
      type:要创建的对象的类型。
      args :与要调用构造函数的参数数量、顺序和类型匹配的参数数组。如果 args 为空数组或空引用(Visual Basic 中为 Nothing),则调用不带任何参数的构造函数(默认构造函数)。
      数组。
      这里的参数args是一个object[]数组类型。它可以传递要创建对象的构造函数中的参数。从这里其实可以得到一个结论:WellKnown激活模式所传递的远程对象类,只能使用默认的构造函数;而Activated模式则可以用户自定义构造函数。activationAttributes参数在这个方法中通常用来传递服务器的url。
      假设我们的远程对象类ServerObject有个构造函数:
      ServerObject(string pName,string pSex,int pAge)
      {
      name = pName;
      sex = pSex;
      age = pAge;
      }
      那么实现的代码是:
      object[] attrs = {new UrlAttribute("tcp://localhost:8080/ServiceMessage")};
      object[] objs = new object[3];
      objs[0] = "wayfarer";
      objs[1] = "male";
      objs[2] = 28;
      ServerRemoteObject.ServerObject = Activator.CreateInstance(
      typeof(ServerRemoteObject.ServerObject),objs,attrs);
      可以看到,objs[]数组传递的就是构造函数的参数。
      b、public static ObjectHandle CreateInstance(string assemblyName, string typeName, object[] activationAttribute);
      参数说明:
      assemblyName :将在其中查找名为 typeName 的类型的程序集的名称。如果 assemblyName 为空引用(Visual Basic 中为 Nothing),则搜索正在执行的程序集。
      typeName:首选类型的名称。
      activationAttributes :包含一个或多个可以参与激活的属性的数组。
      参数说明一目了然。注意这个方法返回值为ObjectHandle类型,因此代码与前不同:
      object[] attrs = {new UrlAttribute("tcp://localhost:8080/EchoMessage")};
      ObjectHandle handle = Activator.CreateInstance("ServerRemoteObject",
      "ServerRemoteObject.ServerObject",attrs);
      ServerRemoteObject.ServerObject obj = (ServerRemoteObject.ServerObject)handle.Unwrap();
      这个方法实际上是调用的默认构造函数。ObjectHandle.Unwrap()方法是返回被包装的对象。
      说明:要使用UrlAttribute,还需要在命名空间中添加:using System.Runtime.Remoting.Activation;

      8基础补充

      通过上面的描述,基本上已经完成了一个最简单的Remoting程序。这是一个标准的创建Remoting程序的方法,但在实际开发过程中,我们遇到的情况也许千奇百怪,如果只掌握一种所谓的“标准”,就妄想可以“一招鲜、吃遍天”,是不可能的。
      1、注册多个通道
      在Remoting中,允许同时创建多个通道,即根据不同的端口创建不同的通道。但是,Remoting要求通道的名字必须不同,因为它要用来作为通道的唯一标识符。虽然IChannel有ChannelName属性,但这个属性是只读的。因此前面所述的创建通道的方法无法实现同时注册多个通道的要求。
      这个时候,我们必须用到System.Collection中的IDictionary接口:
      注册Tcp通道:
      IDictionary tcpProp = new Hashtable();
      tcpProp["name"] = "tcp9090";
      tcpProp["port"] = 9090;
      IChannel channel = new TcpChannel(tcpProp,
      new BinaryClientFormatterSinkProvider(),
      new BinaryServerFormatterSinkProvider());
      ChannelServices.RegisterChannel(channel);
      注册Http通道:
      IDictionary httpProp = new Hashtable();
      httpProp["name"] = "http8080";
      httpProp["port"] = 8080;
      IChannel channel = new HttpChannel(httpProp,
      new SoapClientFormatterSinkProvider(),
      new SoapServerFormatterSinkProvider());
      ChannelServices.RegisterChannel(channel);
      在name属性中,定义不同的通道名称就可以了。
      2、远程对象元数据相关性
      由于服务器端和客户端都要用到远程对象,通常的方式是生成两份完全相同的对象Dll,分别添加引用。不过为了代码的安全性,且降低客户端对远程对象元数据的相关性,我们有必要对这种方式进行改动。即在服务器端实现远程对象,而在客户端则删除这些实现的元数据。
      由于激活模式的不同,在客户端创建对象的方法也不同,所以要分离元数据的相关性,也应分为两种情况。
      (1) WellKnown激活模式:
      通过接口来实现。在服务器端,提供接口和具体类的实现,而在客户端仅提供接口:
      public interface IServerObject
      {
      Person GetPersonInfo(string name,string sex,int age);
      }
      public class ServerObject:MarshalByRefObject,IServerObject
      { ......}
      注意:两边生成该对象程序集的名字必须相同,严格地说,是命名空间的名字必须相同。
      (2) 客户端激活模式:
      如前所述,对于客户端激活模式,不管是使用静态方法,还是使用CreateInstance()方法,都必须在客户端调用构造函数实例化对象。所以,在客户端我们提供的远程对象,就不能只提供接口,而没有类的实现。实际上,要做到与远程对象元数据的分离,可以由两种方法供选择:
      a、利用WellKnown激活模式模拟客户端激活模式:
      方法是利用设计模式中的“抽象工厂”,下面的类图表描述了总体解决方案:
      我们在服务器端的远程对象中加上抽象工厂的接口和实现类:
      public interface IServerObject
      {
      Person GetPersonInfo(string name,string sex,int age);
      }
      public interface IServerObjFactory
      {
      IServerObject CreateInstance();
      }
      public class ServerObject:MarshalByRefObject,IServerObject
      {
      public Person GetPersonInfo(string name,string sex,int age)
      {
      Person person = new Person();
      person .Name = name;
      person.Sex = sex;
      person.Age = age;
      return person;
      }
      }
      public class ServerObjFactory:MarshalByRefObject,IServerObjFactory
      {
      public IServerObject CreateInstance()
      {
      return new ServerObject();
      }
      }
      然后再客户端的远程对象中只提供工厂接口和原来的对象接口:
      public interface IServerObject
      {
      Person GetPersonInfo(string name,string sex,int age);
      }
      public interface IServerObjFactory
      {
      IServerObject CreateInstance();
      }
      我们用WellKnown激活模式注册远程对象,在服务器端:
      //传递对象;
      RemotingConfiguration.RegisterWellKnownServiceType(
      typeof(ServerRemoteObject.ServerObjFactory),
      "ServiceMessage",WellKnownObjectMode.SingleCall);
      注意这里注册的不是ServerObject类对象,而是ServerObjFactory类对象。
      客户端:
      ServerRemoteObject.IServerObjFactory serverFactory =
      (ServerRemoteObject.IServerObjFactory) Activator.GetObject(
      typeof(ServerRemoteObject.IServerObjFactory),
      "tcp://localhost:8080/ServiceMessage");
      ServerRemoteObject.IServerObject serverObj = serverFactory.CreateInstance();
      为什么说这是一种客户端激活模式的模拟呢?从激活的方法来看,我们是使用了SingleCall模式来激活对象,但此时激活的并非我们要传递的远程对象,而是工厂对象。如果客户端要创建远程对象,还应该通过工厂对象的CreateInstance()方法来获得。而这个方法正是在客户端调用的。因此它的实现方式就等同于客户端激活模式。
      b、利用替代类来取代远程对象的元数据
      实际上,我们可以用一个trick,来欺骗Remoting。这里所说的替代类就是这个trick了。既然是提供服务,Remoting传递的远程对象其实现的细节当然是放在服务器端。而要在客户端放对象的副本,不过是因为客户端必须调用构造函数,而采取的无奈之举。既然具体的实现是在服务器端,又为了能在客户端实例化,那么在客户端就实现这些好了。至于实现的细节,就不用管了。
      如果远程对象有方法,服务器端则提供方法实现,而客户端就提供这个方法就OK了,至于里面的实现,你可以是抛出一个异常,或者return 一个null值;如果方法返回void,那么里面可以是空。关键是这个客户端类对象要有这个方法。这个方法的实现,其实和方法的声明差不多,所以我说是一个trick。方法如是,构造函数也如此。
      还是用代码来说明这种“阴谋”,更直观:
      服务器端:
      public class ServerObject:MarshalByRefObject
      {
      public ServerObject()
      {
      }
      public Person GetPersonInfo(string name,string sex,int age)
      {
      Person person = new Person();
      person .Name = name;
      person.Sex = sex;
      person.Age = age;
      return person;
      }
      }
      客户端:
      public class ServerObject:MarshalByRefObject
      {
      public ServerObj()
      {
      throw new System.NotImplementedException();
      }
      public Person GetPersonInfo(string name,string sex,int age)
      {
      throw new System.NotImplementedException();
      }
      }
      比较客户端和服务器端,客户端的方法GetPersonInfo(),没有具体的实现细节,只是抛出了一个异常。或者直接写上语句return null,照样OK。我们称客户端的这个类为远程对象的替代类。
      3、利用配置文件实现
      前面所述的方法,于服务器uri、端口、以及激活模式的设置是用代码来完成的。其实我们也可以用配置文件来设置。这样做有个好处,因为这个配置文件是Xml文档。如果需要改变端口或其他,我们就不需要修改程序,并重新编译,而是只需要改变这个配置文件即可。
      (1) 服务器端的配置文件:
      如果是客户端激活模式,则把wellknown改为activated,同时删除mode属性。
      把该配置文件放到服务器程序的应用程序文件夹中,命名为ServerRemoting.config。那么前面的服务器端程序直接用这条语句即可:
      RemotingConfiguration.Configure("ServerRemoting.config");
      (2)客户端配置文件
      如果是客户端激活模式,修改和上面一样。调用也是使用RemotingConfiguration.Configure()方法来调用存储在客户端的配置文件。
      配置文件还可以放在machine.config中。如果客户端程序是web应用程序,则可以放在web.config中。
      4、启动/关闭指定远程对象
      Remoting中没有提供类似UnregisterWellKnownServiceType()的方法,也即是说,一旦通过注册了远程对象,如果没有关闭通道的话,该对象就一直存在于通道中。只要客户端激活该对象,就会创建对象实例。如果Remoting传送的只有一个远程对象,这不存在问题,关闭通道就可以了。如果传送多个远程对象呢?要关闭指定的远程对象应该怎么做?关闭之后又需要启动又该如何?
      我们注意到在Remoting中提供了Marshal()和Disconnect()方法,答案就在这里。Marshal()方法是将MarshalByRefObject类对象转化为ObjRef类对象,这个对象是存储生成代理以与远程对象通讯所需的所有相关信息。这样就可以将该实例序列化以便在应用程序域之间以及通过网络进行传输,客户端就可以调用了。而Disconnect()方法则将具体的实例对象从通道中断开。
      方法如下:
      首先注册通道:
      TcpChannel channel = new TcpChannel(8080);
      ChannelServices.RegisterChannel(channel);
      接着启动服务:
      先在服务器端实例化远程对象。
      ServerObject obj = new ServerObject();
      然后,注册该对象。注意这里不用RemotingConfiguration.RegisterWellKnownServiceType(),而是使用RemotingServices.Marshal():
      ObjRef objrefWellKnown = RemotingServices.Marshal(obj, "ServiceMessage");
      如果要注销对象,则:
      RemotingServices.Disconnect(obj);
      要注意,这里Disconnect的类对象必须是前面实例化的对象。正因为此,我们可以根据需要创建指定的远程对象,而关闭时,则Disconnect之前实例化的对象。
      至于客户端的调用,和前面WellKnown模式的方法相同,仍然是通过Activator.GetObject()来获得。但从实现代码来看,我们会注意到一个问题,由于服务器端是显式的实例化了远程对象,因此不管客户端有多少,是否相同,它们调用的都是同一个远程对象。因此我们将这个方法称为模拟的SingleTon模式。
      客户端激活模式
      我们也可以通过Marshal()和Disconnect()来模拟客户端激活模式。首先我们来回顾“远程对象元数据相关性”一节,在这一节中,我说到采用设计模式的“抽象工厂”来创建对象实例,以此用SingleCall模式来模拟客户端激活模式。在仔细想想前面的模拟的SingleTon模式。是不是答案就将呼之欲出呢?
      在“模拟的SingleTon”模式中,我们是将具体的远程对象实例进行Marshal,以此让客户端获得该对象的引用信息。那么我们换一种思路,当我们用抽象工厂提供接口,工厂类实现创建远程对象的方法。然后我们在服务器端创建工厂类实例。再将这个工厂类实例进行Marshal。而客户端获取对象时,不是获取具体的远程对象,而是获取具体的工厂类对象。然后再调用CreateInstance()方法来创建具体的远程对象实例。此时,对于多个客户端而言,调用的是同一个工厂类对象;然而远程对象是在各个客户端自己创建的,因此对于远程对象而言,则是由客户端激活,创建的是不同对象了。
      当我们要启动/关闭指定对象时,只需要用Disconnet()方法来注销工厂类对象就可以了。
       
      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.51cto.com/rongfengliang/3118274,作者:rongfengliang,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:HDFS Java 客户端 API

      下一篇:Redis的启动与关闭

      相关文章

      2025-05-19 09:04:44

      js小题2:构造函数介绍与普通函数对比

      js小题2:构造函数介绍与普通函数对比

      2025-05-19 09:04:44
      new , 关键字 , 函数 , 对象 , 构造函数
      2025-05-19 09:04:22

      外设驱动库开发笔记54:外设库驱动设计改进的思考

      外设驱动库开发笔记54:外设库驱动设计改进的思考

      2025-05-19 09:04:22
      使用 , 函数 , 初始化 , 定义 , 对象
      2025-05-19 09:04:22

      外设驱动库开发笔记46:MAX31855热偶变送器驱动

      外设驱动库开发笔记46:MAX31855热偶变送器驱动

      2025-05-19 09:04:22
      对象 , 温度
      2025-05-16 09:15:24

      jQuery遍历对象、数组、集合

      jQuery遍历对象、数组、集合

      2025-05-16 09:15:24
      jQuery , 对象 , 数组 , 遍历 , 集合
      2025-05-14 10:33:31

      计算机初级选手的成长历程——操作符详解(2)

      计算机初级选手的成长历程——操作符详解(2)

      2025-05-14 10:33:31
      对象 , 操作 , 操作符 , 表达式 , 运算 , 逗号 , 逻辑
      2025-05-14 10:33:25

      30天拿下Rust之网络编程

      在现代软件开发中,网络编程无处不在。无论是构建高性能的服务器、实时通信应用,还是实现复杂的分布式系统,对网络编程技术的掌握都至关重要。Rust语言以其卓越的安全性、高性能和优秀的并发模型,为网络编程提供了坚实的基础。

      2025-05-14 10:33:25
      Rust , TCP , 使用 , 客户端 , 异步 , 编程
      2025-05-14 10:33:16

      30天拿下Python之使用Json

      Json的英文全称为JavaScript Object Notation,中文为JavaScript对象表示法,是一种存储和交换文本信息的语法,类似XML。Json作为轻量级的文本数据交换格式,比XML更小、更快,更易解析,也更易于阅读和编写。

      2025-05-14 10:33:16
      json , Json , Python , 字符串 , 对象 , 序列化 , 转换
      2025-05-14 10:33:16

      30天拿下Python之使用网络

      Python网络编程覆盖的范围非常广,包括:套接字编程、socketserver、HTTP和Web开发、异步编程和asyncio等。

      2025-05-14 10:33:16
      Json , TCP , 客户端 , 接字 , 服务器 , 示例 , 连接
      2025-05-14 10:03:05

      C++ 11新特性之bind

      std::bind是C++ 11中<functional>头文件提供的一个函数模板,它允许我们将函数或成员函数与其部分参数预先绑定在一起,形成一个新的可调用对象(英文为:Callable Object)。

      2025-05-14 10:03:05
      bind , std , 函数 , 参数 , 对象 , 绑定 , 调用
      2025-05-14 10:03:05

      C++ 11新特性之右值引用

      C++ 11中引入了一项关键特性——右值引用,极大地增强了C++在资源管理、性能优化和表达力方面的能力。通过理解并合理运用右值引用,我们可以编写出更高效、更简洁且不易出错的代码。

      2025-05-14 10:03:05
      右值 , 对象 , 常量 , 引用 , 构造函数 , 绑定
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5242234

      查看更多

      最新文章

      30天拿下Rust之网络编程

      2025-05-14 10:33:25

      30天拿下Python之使用网络

      2025-05-14 10:33:16

      python 在创建socket之后建立心跳机制

      2025-05-14 09:51:21

      DG搭建过程中备库执行活动复制时报错RMAN-01007、RMAN-01009

      2025-05-13 09:50:59

      Socket类的用法

      2025-05-09 09:30:19

      WebAPI 和 webservice的区别

      2025-05-09 09:21:53

      查看更多

      热门文章

      redis-启动服务端-客户端连接服务端

      2023-03-29 10:07:17

      统计客户端连接数

      2023-05-08 10:00:08

      C/S、B/S、Web的介绍(Web应用开发)

      2023-02-15 08:39:48

      解决rocketmq客户端日志比较大的问题

      2023-03-24 10:33:05

      PHP: ThinkPHP获取客户端IP地址

      2023-02-20 10:15:01

      ×××客户端出现0x80090328错误的解决方法

      2023-05-08 09:58:50

      查看更多

      热门标签

      客户端 实践 基础知识 Java 服务器 java 数据库 框架 python 服务端 学习 代码 简单 javascript 编程
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      30天拿下Rust之网络编程

      C/C++服务器和客户端交互笔记

      初学Android,网络应用之使用多线程Socket(八十五)

      javaWeb服务详解【客户端调用】(含源代码,测试通过,注释) ——EmpService层

      【设计模式之美】【建造型】工厂模式实战:如何设计一个DI框架;梳理流程,通过面向接口解耦对象创建

      网络原理之HTTPS(如果想知道网络原理中有关HTTPS的知识,那么只看这一篇就足够了!)

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号