• com之 代理(proxy)与存根(stub)


    什么是代理和存根 ? 打个比方,你到自动取款机上去取款;你就是客户,取款机就是你的代理;你不会在乎 钱具体放在那里,你只想看到足够或更多的钱从出口出来(这就是com的透明性)。你同银行之间的操作完全是取款机代理实现。 你的取款请求通过取款机,传到另一头,银行的服务器,他也没有必要知道你在哪儿取钱,他所关心的是你的身份,和你取款多少。当他确认你的权限,就进行相应的操作,返回操作结果给取款机,取款机根据服务器返回结果,从保险柜里取出相应数量的钱给你。你取出卡后,操作完成。 取款机不是直接同服务器连接的,他们之间还有一个“存根”,取款机与存根通信,服务器与存根通信。从某种意义上说存根就是服务器的代理。 图1 组件间通信 如上图两个组件之间不是直接通信,而是通过代理和存根来之间的通信来间接实现的。图中的channel是com库的一部分。 COM里,只有进程外组件才会用到代理(proxy)和存根(stub)。 代理在客户的进程内创建,存根在组件com对象的进程中创建。 每个接口的每个函数都有自己的代理和存根。 为什么要用代理和存根 ? 客户为什么要用代理和存根,而不直接同对象连接呢? 给你一个理由,对客户来说,他与所有com对象的连接都是通过指针来调用的, 而对服务来说,调用对象的接口函数也是通过指针来完成的,然而,指针只有在同一进程内才会有效。这样,代理和存根为了完成这个使命也就产生了。 代理和存根的作用不只这些,他还要打包所有的参数(包括接口指针),产生 RPC(远程进程调用),通向另一个进程,或者对象运行所在的另一台机器。 图2 代理的结构 上图所显示的代理结构支持参数的标准列集。每个接口的代理实现了IRpcProxyBuffer接口,用于内聚各个部分之间的相互通信。当代理准备把已列集的参数传递过进程边界时,他调用IRpcChannelBuffer 接口的方法(该接口由channel实现)。channel调用RPC运行库使数据传输到目的地。 图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库会知道怎么做。
  • 相关阅读:
    维护keepalived与mysql漂移脚本
    Linux限制普通用户只能使用某命令
    Android的AlertDialog详解
    android:传感器的使用
    android:wifi
    android: 使用Canvas 绘图
    在 Eclipse 中 配置 tomcat
    android:AIDL
    android之Service 深入剖析
    广播发送者与广播接收者
  • 原文地址:https://www.cnblogs.com/zdxster/p/1945875.html
Copyright © 2020-2023  润新知