一.NET Remoting 介绍

简介

.NET Remoting与MSMQ不同,它不支持离线可得,另外只适合.NET平台的程序进行通信。它提供了一种允许对象通过应用程序域与另一个对象进行交互的框架。.NET 应用程序都在一个主应用程序域中执行的,在一个应用程序域中的代码不能访问另一个应用程序域的数据,然而在某些情况下,我们需要跨应用程序域,与另外的应用程序域进行通信,这时候就可以采用.NET Remoting技术来实现与另一个程序域中的对象进行交互。System.Runtime.Remoting

基本原理

.NET Remoting技术是通过通道来实现两个应用程序之间对象的通信的。

首先,客户端通过Remoting技术的访问通道来获得服务器端对象,再通过代理解析为客户端对象,也称作透明代理,此时获得客户端对象只是服务器对象的一个引用。这既保证了客户端和服务端有关对象的松散耦合,同时优化了通信的性能。在这个过程中,当客户端通过透明代理来调用远程对象的方法时,此时会将调用封装到一个消息对象中,该消息对象包括远程对象信息,被调用的方法名和参数,然后透明代理会将调用委托给真实代理(RealProxy对象)的Invoke方法来生成一个IMethodCallMessage

接着通过序列化把这个消息对象序列化成数据流发送到通道,通道会把数据流传送到服务器端。当服务器接收到经过格式化的数据之后,首先从中通过反序列化来还原消息对象,之后在服务器端来激活远程对象,并调用对应的方法,而方法的返回结果过程则是按照之前的方法反向重复一遍。具体的实现原理图如下所示:


远程对象:

是运行在服务器端的对象,客户端不能直接调用,由于.NET Remoting传递的对象是以引用的方式,因此所传递的远程对象必须继承MarshalByRefObject类,这个类可以使远程对象在.NET Remoting应用通信中使用,支持对象的跨域边界访问。

远程对象的激活方式

在访问服务器端的一个对象实例之前,必须通过一个名为Activation的进程创建它并进行初始化。这种客户端通过通道来创建远程对象的方式称为对象的激活。在.NET Remoting中,远程对象的激活分为两大类:服务器端激活和客户端激活。

1、服务器端激活(WellKnow(知名对象)激活模式)

为什么称为知名对象激活模式呢?是因为服务应用程序在激活对象实例之前会在一个众所周知的统一资源标示符(URI)上发布这个类型,然后该服务器进行会为此类型配置一个WellKnow对象,并根据指定的端口或地址来发布对象。

.NET Remoting把服务器端激活又分为SingleTon模式和SingleCall模式两种。

  •   SingleTon模式:此为有状态模式。.NET Remoting将为所有客户端建立同一个对象实例。服务端只在对象第一次被调用时创建服务对象,当对象处于活动状态时,SingleTon实例会处理所有后来的客户端访问请求,而不管它们是同一个客户端,还是其他客户端。SingleTon实例将在方法调用中一直维护其状态,类似static成员的概念。(相当于Application状态)
  •   SingleCall模式:是一种无状态模式。则当客户端调用远程对象的方法时,Remoting会为每一个客户端建立一个远程对象实例,对象实例的销毁则是由GC自动管理。类似实例成员的概念。(相当于Session状态)

2、客户端激活:

与Wellknow模式不同,。NET Remoting在激活每个对象实例的时候,会给每个客户端激活的类型指派一个URI。客户端激活模式一旦获得客户端的请求,将为每一个客户端都建立一个实例引用。SingleCall模式与客户端激活模式的区别有:

首先,对象实例创建的时间不同。客户端激活方式是客户一旦发出调用请求就实例化,而SingleCall则要等到调用对象方法时再创建。

其次,SingleCall模式激活的对象是无状态的,对象声明周期由GC管理,而客户端激活的对象是有状态的,其生命周期可自定义。

第三,两种激活模式在服务器端和客户端实现的方法不一样,尤其是在客户端,SingleCall模式由GetObject()来激活,它调用对象默认的构造函数,而客户端激活模式,则通过CreateInstance()来激活,它可以传递参数,所以可以调用自定义的构造函数来创建实例。

通道:

在.NET Remoting中时通过通道来实现两个应用程序域之间对象的通信。.NET Remoting中包括4中通道类型:

  1. TcpChannel:Tcp通道使用Tcp协议来跨越.Net Remoting边界来传输序列化的消息流,TcpChannel默认使用二进制格式序列化消息对象,因此具有更高的传输性能,但不提供任何内置的安全功能。

  2. HttpChannel:Http通道使用Http协议在客户端和服务器之间发生消息,使其在Internet上穿越防火墙来传输序列化的消息流。默认情况下,HttpChannel使用Soap格式序列化消息对象,因此它具有更好的互操作性,并且可以使用Http协议中的加密机制来对消息进行加密来保证安全性。因此,通常在局域网内,我们更多地使用TcpChannel,如果要穿越防火墙,则使用HttpChannel。
  3. IpcChannel:进程间通信,只使用同一个系统进程之间的通信,不需要主机名和端口号。而使用Http通道和Tcp通道都要指定主机名和端口号。
  4. 自定义通道:自定义的传输通道可以使用任何基本的传输协议来进行通信,如UDP协议、SMTP协议等。

二、服务端激活方式:SAO

1、创建一个共享接口的dll,服务端和客户端都要引用它。

//定义接口类ITax
//编译生成ITaxTemoting.dll
//服务器端和客户端都要添加该类dll的引用
public interface ITax
{
double GetTax(int salary);
}

创建远程对象,该对象必须继承MarshalByRefObject对象。远程对象类Tax继承了基类MarshalByRefObject和接口ITax。

//定义远程对象,必须继承自MarshalByRefObject
//编译生成TaxRemoting.dll,服务器端必须添加该dll的引用
public class Tax : MarshalByRefObject, ITax
{
private int _callOCunt = 0;
public Tax()
{
Console.WriteLine("Remoting object Tax 已激活");
} //根据税
public double GetTax(int salary)
{
_callOCunt++; return (double)tax;
}
}

2、服务端

需要添加System.Runtime.Remoting.dll引用

定义通道并监听,注册远程对象。信道用于.NET客户端和服务器端的通信。

在.NET Remoting中,是允许同时创建多个通道的,但是.NET Remoting要求通道的名字必须不同,因为名字是用来标识通道的唯一标识符。

TcpChannel channel = new TcpChannel(8085);//定义通道,还有HttpChannel\IPCChannel等
ChannelServices.RegisterChannel(channel, false);//注册通道
RemotingConfiguration.RegisterWellKnownServiceType(typeof(Tax), "Tax1", WellKnownObjectMode.SingleCall);
//在服务端注册一个知名的远程对象Tax,ObjectURI为Tax,知名对象模式为单次调用方式。

3、客户端

注册信道,根据URL获取远程对象代理,使用代理调用服务器端的远程对象。

void Main()
{
TcpChannel channel = new TcpChannel();
ChannelServices.RegisterChannel(channel, false);
ITax obj = (ITax)Activator.GetObject(typeof(ITax), "tcp://localhost:8085/Tax1");//根据URL获取远程对象代理,使用此代理调用服务端的远程对象。
if (obj == null)
{
Console.WriteLine("Could not locate TCP server");
}
Console.WriteLine(obj.GetTax(1).ToString());//调用远程对象的方法获取结果,此时调用服务端的类的默认构造函数实例化。
Console.WriteLine(obj.GetCallCount().ToString()); Console.WriteLine(obj.GetTax(1).ToString());
Console.WriteLine(obj.GetCallCount().ToString());
}
//也可以先为客户端注册类型,再实例化对象(不推荐)
RemotingConfiguration.RegisterWellKnownClientType(typeof(ITax), "tcp://localhost:8085/Tax1");
Tax obj = new Tax();
obj.GetTax();

三、客户端激活方式:CAO

可以调用服务端非默认的带参数的构造函数,服务端为每个客户端保存不同的状态。

1、声明定义一个公共类

public class Tax : MarshalByRefObject, ITax
{
//代码同服务端SAO
}

2、服务端,应用Tax所在的程序集

TcpChannel channel = new TcpChannel(8085);
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.ApplicationName = "Tax1";
RemotingConfiguration.RegisterActivatedServiceType(typeof(Tax));

3、客户端

可以使用Soapsuds.exe分离Tax程序集共客户端调用(即不包含具体的实现内容)

E:>soapsuds -url:http://127.0.0.1:8502/TaxTax1?wsdl -oa:ClientProxy.dll

这将为我们在E盘的根目录下生成ClientProxy.dll文件,这个文件将用于客户端成生代理。

void Main()
{
TcpChannel channel = new TcpChannel();
ChannelServices.RegisterChannel(channel, false);
Tax obj = (Tax)Activator.CreateInstance(typeof(ITax), null, new[] {new UrlAttribute ("tcp://localhost:8085/Tax1")});//根据URL获取远程对象代理,使用此代理调用服务端的远程对象。 Console.WriteLine(obj.GetTax(1).ToString());
Console.WriteLine(obj.GetCallCount().ToString()); Console.WriteLine(obj.GetTax(1).ToString());
Console.WriteLine(obj.GetCallCount().ToString());
} //也可以先为客户端注册类型,再实例化对象(不推荐)
RemotingConfiguration.RegisterActivatedClientType(typeof(ITax), "tcp://localhost:8085/Tax1");//Activator.GetObject
Tax obj = new Tax();
obj.GetTax();

4、关闭注销通道

channel.StartListening(null);
ChannelServices.UnregisterChannel(channel);

四、使用配置文件来重写上面的分布式程序

服务端:

RemotingConfiguration.Configure("RemotingServerHostByConfig.exe.config", false);

服务端的配置文件app.config的内容为

<configuration>
<system.runtime.remoting>
<application>
   <service> <!--服务端,如果是客户端改成Client –>
<wellknown type="Tax" objectUri="Tax1" mode="SingleCall" /> <!--客户端激活改成activator—>
</service>
<channels>
<channel ref="tcp" port="8085" />
</channels>
</application>
</configuration>

客户端:

RemotingConfiguration.Configure("RemotingClientByConfig.exe.config", false);

客户端配置文件的内容为:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<client>
<wellknown type="Tax" url="tcp://localhost:8085/Tax1" />
</client>
<channels>
<channel ref="tcp" port="8085"></channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>

如果想深入了解.NET Remoting技术的话,推荐大家可以看看下面的专题细细品味C#——.Net Remoting专题

WCF之.NET Remoting通讯的更多相关文章

  1. Remoting通讯实例

    Remoting通讯可以实现不同应用程序域之间的通信(可以为一台机器不同程序,也可以不同机器上的不同程序) 实例步骤: (1)编写透明代理类 新建一个类库,命名空间:MyRemoting 在该类库中建 ...

  2. WCF、Net remoting、Web service概念及区别

    Windows通信基础(Windows Communication Foundation,WCF)是基于Windows平台下开发和部署服务的软件开发包(Software Development Kit ...

  3. WCF、.Net Remoting、Web Service概念及区别

    此文章主要参考http://www.cnblogs.com/weiweibtm/archive/2013/06/21/3148583.html 参考书籍<WCF全面解析上册>.<WC ...

  4. 重温WCF之数单向通讯、双向通讯、回调操作(五)

    一.单向通讯单向操作不等同于异步操作,单向操作只是在发出调用的瞬间阻塞客户端,但如果发出多个单向调用,WCF会将请求调用放入到服务器端的队列中,并在某个时间进行执行.队列的存储个数有限,一旦发出的调用 ...

  5. .Net remoting, Webservice,WCF,Socket区别

    传统上,我们把计算机后台程序(Daemon)提供的功能,称为"服务"(service).比如,让一个杀毒软件在后台运行,它会自动监控系统,那么这种自动监控就是一个"服务& ...

  6. 关于通信的关键词UDP/(TCP/IP)/IPC/RPC/.NET Remoting/WebService/WCF/Http 系列

    OSI七层和TCP/IP四层的关系 1.1 OSI引入了服务.接口.协议.分层的概念,TCP/IP借鉴了OSI的这些概念建立TCP/IP模型. 1.2 OSI先有模型,后有协议,先有标准,后进行实践: ...

  7. WCF 通讯标准绑定

    WCF 通讯标准绑定 一.预定义标准绑定 标准绑定 说明 BasicHttpBinding BasicHttpBinding 绑定用于最广泛的互交操作,针对第一代Web服务,所使用的传输协议是HTTP ...

  8. 回顾.NET Remoting分布式开发

    记得在下第一次接触.NET Remoting分布式开发是在2003年,那时候是Framework1.0初次亮相之时,Remoting分布式开发是Framework1.0其中一个亮点.经过多年的发展,在 ...

  9. WCF开发指南之构建服务

    一. 引言 Windows通讯基础(简称为WCF)是一种SDK,用于让你使用典型的CLR编程结构(例如用于发布和消费服务的类和接口等)来构建Windows面向服务的应用程序.WCF的编程模型是声明性的 ...

随机推荐

  1. 日常工作问题解决:配置NTP服务器以及一些常见错误解决

    1.配置NTP服务端 环境:redhat 6.5 服务器主机名 ip地址 说明 server 192.168.57.20 NTP服务端 client 192.168.57.21 NTP客户端 搭建说明 ...

  2. Oracle 数据库 alert日志及trace日志的清理

    Oracle 数据库 alert日志及trace日志的清理 方案一: 暂停数据库的trace 登录到数据库 sqlplus / as sysdba 修改参数: SQL> alter system ...

  3. .NET细节知识总结,不断更新

    1.catch (Exception)和catch (Exception e) Exception 类包含许多子类 程序执行的时候要将每一个类都搜索一遍 以找到符合的异常类 这样是蛮消耗资源的 影响效 ...

  4. SQL入门经典(第四版)学习记录——SQL语法(二)

    一.创建表 create table 表里包含什么类型的数据 表的名称是什么 主键 列的名称是什么 每一列的数据类型是什么 每一列的长度是多少 表里哪些列可以是空的 语法: create table ...

  5. java源码 -- AbstractSet

    AbstractSet抽象类属于Set集合分支的顶层类,它继承了AbstractCollection,实现了Set接口. public abstract class AbstractSet<E& ...

  6. java--带参方法 递归阶乘

    package com.test.day01; // public class TestParam { public void f1(int n){ n =0; } public static voi ...

  7. go defer 语句会延迟函数的执行直到上层函数返回。

    defer code... 可以理解为 执行完当前defer所在的方法代码后执行defer 中的代码 常用在释放资源 比如 关闭文件 为防止忘记编写关闭代码 可以先写好   defer  各种释放资源 ...

  8. Python开发【第三章】:函数介绍

    一. 函数介绍 1.函数是什么? 在学习函数之前,一直遵循面向过程编程,即根据业务逻辑从上到下实现功能,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,也就是将之前实现的代码块复 ...

  9. zookeeper-伪分布式搭建

    1. 下载解压 2. 在conf目录下,新建3个文件(3台服务器):zoo1.cfg.zoo2.cfg.zoo3.cfg zoo1.cfg: tickTime=2000dataDir=/tmp/zoo ...

  10. Solr综合案例深入练习

    1. 综合案例 1.1. 需求 使用Solr实现电商网站中商品信息搜索功能,可以根据关键字.分类.价格搜索商品信息,也可以根据价格进行排序,并且实现分页功能. 界面如下: 1.2. 分析 开发人员需要 ...