看起来是多么美妙的形式啊,完全摆脱了分析RPC时的痛苦,不过我始终还是有疑问,微软如果始终坚持windows操作系统一统的路线,.NET的真正跨平台性是否真正能实现。
一种常见的 Microsoft 理论是:如果需要在不同系统之间进行互操作,应该选择使用开放标准 (SOAP、XML、HTTP) 的 Web 服务方法,而使用 .NET Remoting 决不是一种交互的解决方案;如果各种系统中的所有组件都是 CLR 托管的,则 .NET Remoting“可能”是正确的选择。
我想我还漏了一个重要的问题:串行化(Serialization)。这是实现跨进程调用的关键技术。在COM中串行化使通过列集(marshaling)和散集(unmarshaling)完成的,列集过程的复杂程度因参数类型而异,简单的入WORD或float只需按二进制序列填到数据包中,复杂的参数如指针需要考虑整个指针层次,获得所有的数据全部。散集是和列集向对应的过程,远程机器的存根代码接受到列集数据后,重新建立堆栈的过程就是散集,每次远程调用至少经过两次列集和两次散集,因为返回值也需要列集回来再散集。COM的一个问题就是在于其过于复杂的的参数传递问题这一套复杂的机制是很难搞明白,更何况对于代码的定制了。.NET Remoting对于串行化的处理是通过一个formatter来完成的,.NET Remoting框架给你提供了两个缺省的formatters,SoapFormatter和BinaryFormatter,它们都能通过HTTP或TCP进行传输。在消息完成了ImessageSink对象的预处理链后,它将通过SyncProcessMessage()到达formatter。在客户端,SoapClientFormatterSink将IMessage传给SerializeMessage()方法。这个函数设置TransportHeaders,请求它的NextSink(HttpClientTransportSink ),它将创建一个ChunkedMemoryStream并且传给channel sink.。真正的串行化由CoreChannel.SerializeSoapMessage()开始,它建立一个SoapFormatter,并且调用其Serialize()方法,下面是一个对于obj.setValue(42)方法的SOAP输出
<SOAP-ENV:Envelope
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:i2="http://schemas.microsoft.com/clr/nsassem/General.BaseRemoteObj ***
ect/General">
<SOAP-ENV:Body>
<i2:setValue id="ref-1">
<newval>42</newval>
</i2:setValue>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
- 第4页:.Net远程方法调用研究(4)
- 第5页:.Net远程方法调用研究(5)