做了不少的Remtoing版的Project,对Remoting在Loading Remoting配置内容的过程中到底做了什么,一直没有一个清晰的在内逻辑认识,今天心血来潮,investigate一番,于是就有了这篇Post,以供大家赏析,另外也对那些希望新建自己的ServerSink有些一些帮助:
Remoting Server Initialize process,一般如以下步骤所示:
1. 一般服务端程序会以:System.Runtime.Remoting.RemotingConfiguration.Configure(”server.exe.config”),开始Loading 的第一步,该函数会根据配置文件内容初始化Server端的Remoting运行期架构体系。
2. 在上面的Configure(”server.exe.config”)中,会调用 System.Runtime.Remoting.RemotingConfigHandler.ConfigureRemoting(),该函数根据”server.exe.config”中的以下配置内容为例: <system.runtime.remoting>
<application>
<channels>
<channel ref="http" port="5555">
<serverProviders>
<provider type="MyServerSink.MyServerSinkProvider, MyServerSink"/>
<formatter ref="soap"/>
</serverProviders>
</channel>
</channels> </application> </system.runtime.remoting>来初始化Server的Remoting运行期架构体系。
3. 在上面的ConfigureRemoting()中,会调用System.Runtime.Remoting.RemotingConfigHandler.CreateServerChannelSinkProviderChain(ArrayList entries),该函数根据以下配置内容为例: <serverProviders> (注意:这里的配置顺序和“Client”配置顺序恰好相反) <provider type="MyServerSink.MyServerSinkProvider, MyServerSink"/> <formatter ref="soap"/> </serverProviders>来创建ServerSinkProviderChain链表,按照该配置顺序,先创建MyServerSink.MyServerSinkProvider对象,再创建SoapServerFormatterSinkProvider对象,然后把SoapServerFormatterSinkProvider对象,赋值给MyServerSinkProvider1对象的Next属性(在后面,通过该属性可以递归创建ServerChannelSinkChain链表)(这是个递归创建的过程,下一个被创建的对象赋值给上一个被创建对象的Next属性)。
4. 在上面的ConfigureRemoting()中,会根据<channel ref="http" port="5555">,创建ServerChannel通道:构造HttpChannel对象,在构造HttpChannel对象过程中,会构造HttpServerChannel对象,其实HttpServerChannel才是真正起作用的的对象(IChannelReceiver),以"5555"作为侦听端口。
5. 在HttpServerChannel对象的SetupChannel()中,调用CreateServerChannelSinkChain()过程中,以创建ServerChannelSinkChain链表。
6. 在上面的CreateServerChannelSinkChain()过程中,会遍历前面所创建的 ServerSinkProviderChain链表,按照逆向顺序,通过SoapServerFormatterSinkProvider对象的CreateSink(),调用SoapServerFormatterSink构造函数,返回一个SoapServerFormatterSink对象,再通过MyServerSinkProvider对象的CreateSink(),调用MyServerSink构造函数,返回一个MyServerSink对象,并把SoapServerFormatterSink对象赋值给MyServerSink对象的Next属性,从而建立起ServerSinkProviderChain链表。其实这个过程用代码来表达是非常简单的(_nextProvider起到关键作用):
// create sinks of the next SinkProvider in the chain
IServerChannelSink next = _nextProvider.CreateSink(channel); return new MyServerSink(next);
下图是以一下配置文件,初始化后的架构图:初探.Net Remoting服务端 Loading Remtoing配置内容的过程
<serverProviders> (注意:这里的配置顺序和“Client”配置顺序恰好相反)
<provider type="MyServerSink1.MyServerSinkProvider1, MyServerSink1"/>(和Client端的MyClientSink1对应)
<formatter ref="soap"/>
<provider type="MyServerSink2.MyServerSinkProvider2, MyServerSink2"/>(和Client端的MyClientSink2对应)
</serverProviders>
《初探.Net Remoting客户端 Loading Remtoing配置内容的过程 》已经推出。 也许我上面说了一大堆,还不如大家看一下具体的源代码来得清楚。以文章中的实例代码,请从《实现一个压缩Remoting传输数据的Sink:CompressionSink》下载。