在本人的上一篇文章中只是简单的介绍了一下.NETRemoting的一般概念和基本的使用。这篇文章我想通过自己的学习和理解将对.NETRemoting的整体的一个框架进行通俗的讲解,其中最重要的就是信道(管道)处理模型思想,这里面蕴含了很多的设计原理。[王清培版权所有,转载请给出署名]
.NETRemoting远程处理架构是一个半成品,是.NET给我们的扩展框架,要想用于商业项目必须进行一些安全、性能方面的控制。要想进行一定深度的扩展那就要必须了解它的整体结构,各个点之间的关系才能很好的控制它。
网上讲解.NETRemoting的文章很多,但是通俗易懂的没有几篇,都是大概讲解了一下整体模型或者从MSDN上COPY过来,未能对各模型之间的接口做详细讲解。了解.NETRemoting的朋友都知道,它的实现基本上都是通过接口与接口之间的串联形成处理管道,这也让我们想起来了设计模式中首要提及的面向对象设计思想“面向接口编程”。
本人在学习.NETRemoting的时候还是比较痛苦的,由于中文资料缺乏只能通过搜索网上零零散散的知识点再通过拼命的理解、换位思考、提高抽象层次,才终于参透为什么那么多接口之间的关系,在这里小弟会一一讲解那些诸如IClientChannelSink、IClientChannelSinkProvider、IMessageSink等等接口到底是什么意思,提供程序与信道接收器之间又是啥关系,在信道处理模型中是怎么利用多态来设计的。
.NETRemoting处理管道
在.NETRemoting中它的整体处理模型有点像ASP.NET中的HTTP处理管道模型,消息从最上面的入口进入然后一个一个的传递到各个处理模块中,这样就形成了一个抽象的处理管道。
图1(客户端信道处理):
这是客户端信道处理模型的大概结构。任何客户端对跨远程处理都是通过代理进行的,代理分为两部分一种是透明代理,一种是真实代理;
透明代理是通过真实代理动态生成的,透明代理的所有成员都是客户端将要调用的远程对象的一个虚拟镜像。为什么要说是虚拟的,是因为透明代理只是方便客户端调用的,当我们NEW一个远程对象时,系统将为我们动态的生成一个继承自你NEW的那个对象的代码,然后动态生成内存透明代理对象。
透明代理包括了对真实代理的调用,真正的幕后主脑是RealProxy对象,它包括了对信道处理结构的引用。在上面的图1中为什么真实代理是用IMessageSink接口来启动整个信道处理模型的。这里也是最为难理解的入口点,下面我们将自己的抽象能力提升一个层次才能知道系统为什么要这样设计。[王清培版权所有,转载请给出署名]
图2:(服务器端信道处理)
.NETRemoting饶人的名词解释
不管是服务器端还是客户端都是通过信道处理模型来对双方的消息进行一系列的处理。客户端的信道处理和服务器端的信道处理有点区别,这些区别是来自它们的更高层次的抽象。这句话可能根本不好理解,从我上面的两幅图中我想读者多多少少能理解点意思来,在信道处理管道中都是通过每个信道接收器提供程序来创建有处理能的信道接收器。
我们先来解决一些会给我们理解带来困扰的英文单词:
Channel:在系统中它表示信道,也就是处理管道。
IChannel:表示一个抽象的处理管理,用来标识一个管道的信息,如管道名称,管道级别之类的。
Sink:接收器,也就是管道中的消息处理环节,系统通常用这个单词来组合,也会让初学者容易参数混淆(看过这篇文章后你就不会在混淆了)。
Provider:一般表示为提供程序,在.NETRemoting里面的提供程序这是某些环境的一个入口点,比如在系统中序列化环节,系统通过SoapClientFormatterSinkProvider提供程序来创建SoapClientFormatterSink信道接收器,这里的提供程序是表示即将进入处理过程,这个处理过程表示某一个处理环节,在这个处理环节中可能包括很多用来接收要处理的信息,所有叫做信息接收器,也就是sink结尾的接口。
IClientChannelSinkProvider:客户端信道接收器提供程序,也就是图1中表示的每个对消息的处理环节部分。该接口有一个NEXT属性用来连接下一个提供程序,这样就串联起一个抽象的处理管道。我们要记住提供程序这是创建处理环节的入口点,真正用来处理消息的是sink结尾的接口,这里也就是IClientChannelSInk对象。
IClientChannelSink:客户端消息接收器,用于在管道处理中对消息的传递进行个性化修改,我们可以在这个里面进行一些消息传递的压缩、编码等等。
IServerChannelSinkProvider:服务器端信道接收器提供程序,和客户端是相同的功能,都是用来创建信息接收器用的,只不过这里是服务器端的信息处理。
IServerChannelSink:服务器端消息接收器,用来在服务器端进行消息的处理,可以对传输过来的消息进行解压缩、反编码等等,与客户端功能是对应的。
IMessageSink:入门的朋友可能会对这个接口参数误解,这是啥接口啊?我不是有了Sink类型的接口了吗?为什么还要消息接口?其实这里也很好理解,为什么需要各种各样的接口,这就是我上面所说的“将自己的抽象能力提升一个高度”才能理解。如果对接口编程不是很熟悉的朋友可能是不太好理解。每种接口表示某种抽象,我打个比方,如果有一个对象它既实现了IMan接口,又实现了IDog接口,它在与人交流的时候我们知道它是实现了人类接口的对象,所以我们认识它并且能与它进行交流,如果它与狗交流的话那么狗狗也是认识它的因为它也实现了狗的接口。从这里讲,实现多个接口的对象具有很深的抽象层次,在某些场合它被视为一种类型,在另外一些场合它又被视为另一种类型。下面我们讲到具体的接口实现时,就明白我所说的意思了。
.NETRemoting信道接收器
上面的名词解释的差不多了,我们来动动手吧;
按照上面的客户端信道模型图,我们先来实现一个IClientChannelSinkProvider接口,我们将利用这个接口来创建一个能处理消息的IClientChannelSink接口。
-
usingSystem;
-
usingSystem.Collections.Generic;
-
usingSystem.Collections;
-
usingSystem.Text;
-
usingSystem.Runtime.Remoting;
-
usingSystem.Runtime.Serialization.Formatters;
-
usingSystem.Runtime.Remoting.Channels;
-
usingSystem.Runtime.Remoting.Lifetime;
-
usingSystem.Runtime.Remoting.Channels.Http;
-
usingSystem.Runtime.Remoting.Channels.Tcp;
-
usingSystem.Runtime.Remoting.Channels.Ipc;
-
-
namespaceMyClassLibrary.CustomProvider
-
{
-
publicclassClientCustomProvider:IClientChannelSinkProvider
-
{
-
#regionIClientChannelSinkProvider成员
-
-
-
-
-
-
-
-
publicIClientChannelSinkCreateSink(IChannelSenderchannel,stringurl,objectremoteChannelData)
-
{
-
returnnewClientCustomSink(Next.CreateSink(channel,url,remoteChannelData));
-
}
-
-
-
-
publicIClientChannelSinkProviderNext{get;set;}
-
-
#endregion
-
}
-
}
这里是我们创建客户端接收器提供程序的代码,在这里我们创建个一个ClientCustomSink信道接收器对象,但是在构造函数中我们用NEXT属性又创建了一个信道接收器作为参数传入到对象,这样做的目的就是能保证每一个消息接收器处理完成后能接着传递给下一个信息接收器处理。
-
usingSystem;
-
usingSystem.Collections.Generic;
-
usingSystem.Collections;
-
usingSystem.Text;
-
usingSystem.Runtime.Remoting;
-
usingSystem.Runtime.Serialization.Formatters;
-
usingSystem.Runtime.Remoting.Channels;
-
usingSystem.Runtime.Remoting.Lifetime;
-
usingSystem.Runtime.Remoting.Channels.Http;
-
usingSystem.Runtime.Remoting.Messaging;
-
usingSystem.Runtime.Remoting.Channels.Tcp;
-
usingSystem.Runtime.Remoting.Channels.Ipc;
-
-
namespaceMyClassLibrary.CustomProvider
-
{
-
publicclassClientCustomSink:BaseChannelSinkWithProperties,IClientChannelSink
-
{
-
IClientChannelSinknextchannelsink;
-
publicClientCustomSink(IClientChannelSinknextchannel)
-
{
-
nextchannelsink=nextchannel;
-
}
-
#regionIClientChannelSink成员
-
-
publicvoidAsyncProcessRequest(IClientChannelSinkStacksinkStack,IMessagemsg,ITransportHeadersheaders,System.IO.Streamstream)
-
{
-
nextchannelsink.AsyncProcessRequest(sinkStack,msg,headers,stream);
-
}
-
-
publicvoidAsyncProcessResponse(IClientResponseChannelSinkStacksinkStack,objectstate,ITransportHeadersheaders,System.IO.Streamstream)
-
{
-
nextchannelsink.AsyncProcessResponse(sinkStack,state,headers,stream);
-
}
-
-
publicSystem.IO.StreamGetRequestStream(IMessagemsg,ITransportHeadersheaders)
-
{
-
msg.Properties.Add("自定义消息","自定义消息值");
-
returnnextchannelsink.GetRequestStream(msg,headers);
-
}
-
-
publicIClientChannelSinkNextChannelSink
-
{
-
get{returnnextchannelsink;}
-
}
-
-
publicvoidProcessMessage(IMessagemsg,ITransportHeadersrequestHeaders,System.IO.StreamrequestStream,outITransportHeadersresponseHeaders,outSystem.IO.StreamresponseStream)
-
{
-
nextchannelsink.ProcessMessage(msg,requestHeaders,requestStream,outresponseHeaders,outresponseStream);
-
}
-
publicIDictionaryNextProperise
-
{
-
get{returnnextchannelsink.Properties;}
-
}
-
#endregion
-
}
-
}
有一这里的代码太长我就不加注释了。这个对象主要实现了IClientChannelSink接口,也就是信道接收器接口,在这个接口面明前比Provider提供程序多了很多东西。这里才是真正处理的地方,系统为了代码的整洁性将提供程序与信息接收器分离开,其实也可以将这两个接口进行合并。在构造函数里面我们用一个私有的IClientChannelSink保存了下一个Sink。该对象还实现了BaseChannelSinkWithProperties抽象类,这个类是用来获取下一个信道接收器的内部属性用的。如果我们没有实现这个抽象类就要自己实现NextProperise属性。[王清培版权所有,转载请给出署名]
其实在IClientChannelSink里面比较重要的就是GetRequestStream和ProcessMessage两个方法,一个是用来获取即将要发送的Stream流,一个是进行发送的方法。为了便于大家的理解,请看图3:
我上面的处理流程不一定就是GetRequestStream是第一步,但是它是ProcessMessage方法的上一步,所以我用1、2表示。当GetRequestStream到了最后一个Sink时,系统将进行最后的调用,也就是进行远程发送了。
在GetRequestStream中我们加入了一些自己定义的数据,我们在通过服务器端的IServerChannelSink获取这消息。
-
usingSystem;
-
usingSystem.Collections.Generic;
-
usingSystem.Collections;
-
usingSystem.Text;
-
usingSystem.Runtime.Remoting;
-
usingSystem.Runtime.Serialization.Formatters;
-
usingSystem.Runtime.Remoting.Channels;
-
usingSystem.Runtime.Remoting.Lifetime;
-
usingSystem.Runtime.Remoting.Channels.Http;
-
usingSystem.Runtime.Remoting.Messaging;
-
usingSystem.Runtime.Remoting.Channels.Tcp;
-
usingSystem.Runtime.Remoting.Channels.Ipc;
-
-
namespaceMyClassLibrary.CustomProvider
-
{
-
publicclassServerCustomSink:BaseChannelSinkWithProperties,IServerChannelSink
-
{
-
privateIServerChannelSinkiserverchannelsink;
-
publicServerCustomSink(IServerChannelSinkserverchannel)
-
{
-
iserverchannelsink=serverchannel;
-
}
-
#regionIServerChannelSink成员
-
-
publicvoidAsyncProcessResponse(IServerResponseChannelSinkStacksinkStack,objectstate,IMessagemsg,ITransportHeadersheaders,System.IO.Streamstream)
-
{
-
if(iserverchannelsink!=null)
-
iserverchannelsink.AsyncProcessResponse(sinkStack,state,msg,headers,stream);
-
thrownewNotImplementedException();
-
}
-
-
publicSystem.IO.StreamGetResponseStream(IServerResponseChannelSinkStacksinkStack,objectstate,IMessagemsg,ITransportHeadersheaders)
-
{
-
if(iserverchannelsink!=null)
-
iserverchannelsink.GetResponseStream(sinkStack,state,msg,headers);
-
thrownewNotImplementedException();
-
}
-
-
publicIServerChannelSinkNextChannelSink
-
{
-
get{returniserverchannelsink;}
-
}
-
-
publicServerProcessingProcessMessage(IServerChannelSinkStacksinkStack,IMessagerequestMsg,ITransportHeadersrequestHeaders,
-
System.IO.StreamrequestStream,outIMessageresponseMsg,outITransportHeadersresponseHeaders,outSystem.IO.StreamresponseStream)
-
{
-
sinkStack.Push(this,"ok");
-
returnNextChannelSink.ProcessMessage(sinkStack,requestMsg,requestHeaders,requestStream,outresponseMsg,outresponseHeaders,outresponseStream);
-
}
-
-
#endregion
-
-
}
-
}
图4:
总结:
.NETRemoting是一个非常成熟的CLR远程处理框架,其实现的原理也很复杂,基本上每一部分都可以扩展,它的内部实现都是通过面向接口来的,接口的粒度也非常小。从IXXXChannelSinkProvider和IXXXChannelSink两种接口就可以看出来,里面的空间很大。
本篇文章只是本人在学习.NETRemoting过程中的一点小小的感悟献给那些还没有搞清楚Remoting的基本框架的朋友。谢谢
分享到:
相关推荐
欧柏泰克:.NET 简谈面向接口编程 面向接口编程是一种高抽象的开发模式,旨在将类与类之间的关系提升到一个更高的抽象层次。这种编程方式可以帮助开发人员更好地设计和实现软件系统,从而提高开发效率和质量。 在...
本文将详细介绍.NET中的事务处理机制,包括本地事务处理、分布式事务处理以及如何使用这些技术来提高应用程序的可靠性和一致性。 #### 二、本地事务处理 本地事务处理是指在一个单一的资源管理器(如单个数据库)内...
[王清培版权所有,转载请给出署名](可以参考本人的:.NET简谈事务本质论、.NET简谈自定义事务资源管理器)什么叫可逆的?程序的执行是可以被无限制回滚的。什么叫可逆的框架?实现了对可逆功能的封装,并能通过简单的...
简谈校园网络安全方案的设计.pdf
React.PureComponent通过浅层比较props和state来实现shouldComponentUpdate方法,这有助于减少不必要的渲染,从而提高组件的性能,特别是对于大型列表和表格等复杂组件结构。 然而,它只能进行浅比较,如果组件的...
【标题】:简谈三菱PLC编程软件概要 【描述】:本文旨在概述三菱PLC编程软件的主要特点和用途,适用于不同的三菱可程序设计控制器系列。 【标签】:互联网,cs 【正文】: 三菱PLC编程软件是工业自动化领域广泛...
### 知识点生成:简谈Ubuntu之DIY发行版 #### 1. 概述 随着二十一世纪的到来,个性化需求愈发明显,这不仅体现在日常生活中,也体现在技术领域,比如自定义操作系统(OS)。本文将详细介绍如何通过简单的步骤DIY一...
【标题】:简谈三菱PLC编程软件 【描述】:本文主要探讨了三菱可编程逻辑控制器(PLC)的编程软件,包括不同系列的软件特点及其在编程、监控、调试和维护中的应用。 【标签】:互联网 cs 【正文】: 三菱PLC编程...
【标题】:简谈三菱PLC编程软件概要 【描述】:本文将详细解析三菱PLC编程软件的各类工具,包括其功能、适用范围以及如何利用这些软件进行编程、调试和维护工作。 【标签】:互联网,cs 在工业自动化领域,三菱...
《城市的时尚面孔:简谈服装专卖店的橱窗设计》 城市的时尚面孔往往通过服装专卖店的橱窗得以展现,这不仅是一场视觉盛宴,更是品牌文化和销售策略的重要载体。橱窗设计,作为销售的前奏,它融合了创意、造型、色彩...
简谈Windows下的反调试技术 简谈Windows下的反调试技术 简谈Windows下的反调试技术 简谈Windows下的反调试技术 简谈Windows下的反调试技术 简谈Windows下的反调试技术
### 简谈JDK动态代理 #### 一、引言 JDK动态代理机制是Java反射机制的一个重要应用,它允许程序在运行时创建一个实现了特定接口的新类实例,并且能够控制这些新类实例的方法调用行为。这种机制不仅提高了代码的灵活...
为了应对工业生产中的严酷环境,这些组件通常采用不锈钢等高质量材料制造,确保在恶劣条件下仍能保持其结构的完整性和可靠性。同时,设计上还会考虑防火需求以及日常维护的便捷性。 在设计机械联锁安全系统时,首要...
简谈工程项目成本管理.doc
简谈公司员工绩效承诺.doc
房地产开发流程简谈.pptx