NET Remoting一,二(收藏转帖http://www.rainsts.net/article.asp?id=408)_henreash的博客-程序员信息网

技术标签: C#_Remoting  tcp  server  system  服务器  wcf  class  

有太多的原因让我忽略了 Remoting,不过现在用它来开始 SOA 和 WCF 的旅途还是不错的选择。.NET Remoting 封装了分布式开发的消息编码和通讯方式,让我们用非常简单的方式既可完成不同模式的分布系统开发,同时其可配置、可扩展的特性也让我们拥有极大的灵活性。当然,我更看好其升级版本 —— WCF。

要了解 Remoting 的基本信息和介绍,还是看 MSDN 比较好。先写一个简单的 Example 来体验一下,为了方便,我直接在一个工程里面创建不同的应用程序域来模拟分布模式。
using System;
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 RemotingTest
  {
    /// <summary>
    /// 远程类型
    /// </summary>
    public class Data : MarshalByRefObject
    {
      private int i;

      public int I
      {
        get { return i; }
        set { i = value; }
      }

      public void Where()
      {
        Console.WriteLine("{0} in {1}", this.GetType().Name, AppDomain.CurrentDomain.FriendlyName);
      }
    }

    /// <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);

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

      // 判断是否是代理
      Console.WriteLine(RemotingServices.IsTransparentProxy(data));
    }

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


在 Remoting 中,核心内容包括 "远程对象" 和 "信道",前者是我们要使用的内容,后者则提供了分布环境的封装。使用 Remoting 一般包括如下步骤:

1. 创建可远程处理的类型。
2. 注册信道。
3. 注册远程类型(以及其激活方式)。
4. 创建远程对象代理,完成调用。

后面的章节将就这些内容去做点研究。 

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

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

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

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>
    [Serializable]
    public class Data
    {
      private int i;

      public int I
      {
        get { return i; }
        set { i = value; }
      }

      public void Where()
      {
        Console.WriteLine("{0} in {1}", this.GetType().Name, AppDomain.CurrentDomain.FriendlyName);
      }
    }

    /// <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 = Activator.CreateInstance(typeof(Data)) as Data;
      data.Where();

      // 判断是否是代理
      Console.WriteLine(RemotingServices.IsTransparentProxy(data));
    }

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


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

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

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 int i;

      public int I
      {
        get { return i; }
        set { i = value; }
      }

      public void Where()
      {
        Console.WriteLine("{0} in {1}", this.GetType().Name, AppDomain.CurrentDomain.FriendlyName);
      }
    }

    /// <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);

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

      // 判断是否是代理
      Console.WriteLine(RemotingServices.IsTransparentProxy(data));
    }

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


输出:
Data in server
True

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

 

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/henreash/article/details/2220029

智能推荐

C语言稀疏矩阵一次定位快速转置算法_Zzzgxz的博客-程序员信息网

稀疏矩阵一次定位快速转置算法//稀疏矩阵一次定位快速转置算法//4-20 by Zzzgxz// 一次定位的位置在指的是在三元表中的位置#include &lt;stdlib.h&gt;#include&lt;stdio.h&gt;#define MAXSIZE 1000typedef struct{ int row; int col; int e;}Triple;typedef struct{ Triple data[MAXSIZE - 1];

三种方式,教你优雅的替换if-else语句!_程序员的成长之路的博客-程序员信息网

程序员的成长之路互联网/程序员/技术/资料共享关注阅读本文大概需要 2.8 分钟。来自:love1024.blog.csdn.net/article/details/104955363场...

关于字节数组的转换_sjzwenzi的博客-程序员信息网

关于字节数组的转换 byte[] mybyte = new byte[10]; mybyte[0] = 0; mybyte[1] = 34; mybyte[2] = 255; mybyte[3] = 254; string s = "abcdfgh

放弃循环依赖 linux,--aid 解决rpm安装过程中循环依赖_weixin_39736606的博客-程序员信息网

redhat的包管理怎么都比apt要差些,有时候会被他的依赖弄得想杀人了.....你安装一个包,结果他告诉你依赖另外一个包,再安装那个包,又是依赖下一个.....特别当产生循环依赖的情况下,很让人郁闷,如下:libselinux-1.33.4-5.5.el5.i386.rpmlibselinux-devel-1.33.4-5.5.el5.i386.rpmlibselinux-python-1.33...

Mac 终端解压缩命令大全_chase…的博客-程序员信息网_mac终端解压命令

tar解包:tar xvf FileName.tar打包:tar cvf FileName.tar DirName(注:tar是打包,不是压缩!)———————————————.gz解压1:gunzip FileName.gz解压2:gzip -d FileName.gz压缩:gzip FileName———————————————.tar.gz 和 .tgz解压:tar zxvf FileName.tar.gz压缩:tar zcvf FileName.tar.gz DirName

一些 iOS问题解决_XLsn0w的博客-程序员信息网

1.解析详情页(是webView)遇到的3个问题:1.图片太大,超出屏幕范围2.怎么在webView上面添加一行文字3.文字太小1.解决方法webView.scalesPageToFit =YES;2.字符串拼接html代码3.解决方法设置代理- (void)webViewDidFinishLoad:(UIWebView *)webView{[w

随便推点

Android Update Engine分析(五)服务端核心之Action机制_洛奇看世界的博客-程序员信息网

Android Update Engine分析(五)服务端核心之Action机制前面四篇分别分析了Makefile,Protobuf和AIDL相关文件, Update Engine的客户端进程update_engine_client以及Update Engine的服务端:Android Update Engine分析(一)MakefileAndroid Update Engine分析(...

CISCO VRRP配置_会飞的猪@123的博客-程序员信息网_思科vrrp

CISCO VRRP配置VRRPVRRP:虚拟路由器冗余性协议和HSRP不同,可以使用一台路由器的真实IP地址。在VRRP中,有一台主用的(master)路由器,以及一台或者多台的备用(backup)路由器。VRRP的三种状态1)Initialize系统启动后进入此状态,当收到接口startup的消息,将转入Backup (优先级不为255时)或Master状态(优先级为255时)。...

[从零开始学习FPGA编程-34]:进阶篇 - 基本时序电路-计数器(Verilog语言)_文火冰糖的硅基工坊的博客-程序员信息网_fpga计数器程序verilog

作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_程序员信息网本文网址: 目录第1章 计数器的工作原理1.0 计数器在时序电路中的位置1.1 计数器概述1.2 计数器的组成1.3 计数器的应用1.4 计数器的种类第2章 8bits二进制计数器的Verilog实现2.1 全部代码2.2 计数器行为描述的简化方式2.3 通过for循环描述计数器的行为狭义的计数器是指一些常用计时器,例如体育比赛中测试时间的计时器等,但本词条所要介绍的并不是这种计时器,要介绍的是应用更为广泛的时序逻辑电

用拉普拉斯变换求零状态响应_高斯拉普拉斯算子(Laplacian of Gaussian, LoG)_weixin_39834475的博客-程序员信息网

一、简要描述:拉普拉斯算子是图像二阶空间导数的二维各向同性测度。拉普拉斯算子可以突出图像中强度发生快速变化的区域,因此常用在边缘检测任务当中。在进行Laplacian操作之前通常需要先用高斯平滑滤波器对图像进行平滑处理,以降低Laplacian操作对于噪声的敏感性。该操作通常是输入一张灰度图,经过处理之后输出一张灰度图。 二、工作原理记图片像素的强度值为 ,其所对应的拉普拉斯算子 如下所示: ...

对accuracy、precision、recall、F1-score、ROC-AUC、PRC-AUC的一些理解_weixin_30919919的博客-程序员信息网

  最近做了一些分类模型,所以打算对分类模型常用的评价指标做一些记录,说一下自己的理解。使用何种评价指标,完全取决于应用场景及数据分析人员关注点,不同评价指标之间并没有优劣之分,只是各指标侧重反映的信息不同。为了便于后续的说明,先建立一个二分类的混淆矩阵 ,以下各参数的说明都是针对二元分类 ...

zabbix5.0版本监控环境安装部署(CentOS7.5)_蜗牛速度在更新的博客-程序员信息网_zabbix5.0安装部署

zabbix官方网址:https://www.zabbix.com/cn/download?zabbix=5.0&amp;os_distribution=centos&amp;os_version=7&amp;db=mysql&amp;ws=nginx基于LNMP模式,进行安装部署。zabbix5.0中文使用手册https://www.zabbix.com/documentation/5.0/zh/manual/quickstart/loginzabbix原理图示如下图,也可

推荐文章

热门文章

相关标签