COM代理与存根

什么是代理和存根 ?

 

打个比方,你到自动取款机上去取款;你就是客户 ,取款机就是你的代理 ;你不会在乎

钱 具体放在那里,你只想看到足够或更多的钱从出口出来(这就是com的透明性)。你同银行之间的操作完全是取款机代理实现。 你的取款请求通过取款机,传到另一头,银行的服务器,他也没有必要知道你在哪儿取钱,他所关心的是你的身份,和你取款多少。当他确认你的权限,就进行相应 的操作,返回操作结果给取款机 ,取款机根据服务器返回结果,从保险柜里取出相应数量的钱给你。你取出卡后,操作完成。 取款机不是直接同服务器连接的,他们之间还有一个“存根”,取款机与存根通信,服务器与存根通信。从某种意义上说存根就是服务器的代理。

COM代理与存根_第1张图片

图1 组件间通信

如上图两个组件之间不是直接通信,而是通过代理和存根来之间的通信来间接实现的。图中的channel是com库的一部分。

       COM里,只有进程外组件才会用到代理(proxy)和存根(stub)。

代理在客户的进程内创建,存根在组件com对象的进程中创建。 每个接口的每个函数都有自己的代理和存根。

为什么要用代理和存根 ?

 

客 户为什么要用代理和存根,而不直接同对象连接呢?给你一个理由,对客户来说,他与所有com对象的连接都是通过指针来调用的, 而对服务来说,调用对象的接口函数也是通过指针来完成的,然而,指针只有在同一进程内才会有效。这样,代理和存根为了完成这个使命也就产生了。

代理和存根的作用不只这些,他还要打包所有的参数(包括接口指针),产生 RPC(远程进程调用),通向另一个进程,或者对象运行所在的另一台机器。

COM代理与存根_第2张图片

图2 代理的结构

上图所显示的代理结构支持参数的标准列集。每个接口的代理实现了IRpcProxyBuffer 接口,用于内聚各个部分之间的相互通信。当代理准备把已列集的参数传递过进程边界时,他调用IRpcChannelBuffer 接口的方法(该接口由channel实现)。channel调用RPC运行库使数据传输到目的地。

COM代理与存根_第3张图片

图3 存根的结构

如上图所示,每个接口的存根被连接到对象的相应接口上。chnnel分发传入的消息到适当的接口的存根。所有的组件通过IRpcChannelBuffer 接口与chnnel交流,这个接口提供了与RPC运行库的连接。

列集(marshalling)

说到代理和存根,自然少不了列集,什么是列集?

列集 ,对函数参数进行打包处理得过程,因为指针等数据,必须通过一定得转换,才能被另一组件所理解,列集完成后,RPC调用就会产生。可以说列集是一种数据格式的转换方法。

列集有3种方式:

1. 类型库列集

它可以列集与OLEAUTOMATION兼容的任何接口,意思是你的接口的返回值必须是HRESULT,所使用的参数的类型也应该是与C++的VARIANT结构兼容。

2. 通过创建Stub / proxy DLL

这个DLL的源代由MIDL产生。你必须在服务器和客户机上都注册这个DLL(这是标准的marshal 方式)使用吃方法时,最好把stub / proxy代码编译作为一个独立的组件。

3. 自定义marshaling

自 定义marshal要求在你的组件中必须实现IMarshal接口。当COM需要marchal时,他首先通过QueryInterface看你是否支 持IMarshal接口,如果你实现了该接口,也就是说,由你控制了你的COM的所有参数和返回值的打包、解包的方法模式。

代理和存根dll的建立

使用工具MIDL,对一个IDL文件,MIDL会分析自动产生相应的代理/存根 DLL的相关文件。

怎么使用代理和存根

对于你来说代理和存根的使用是透明的,你根本不用去关心如何使用他们,com库会知道怎么做。

你可能感兴趣的:(windows)