资源预览内容
第1页 / 共61页
第2页 / 共61页
第3页 / 共61页
第4页 / 共61页
第5页 / 共61页
第6页 / 共61页
第7页 / 共61页
第8页 / 共61页
第9页 / 共61页
第10页 / 共61页
亲,该文档总共61页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
5、DCOMDCOMDCOMCOM特性 语言无关性 二进制 复用性 包含方式 聚合方式 进程透明性 进程内服务程序: DLL 本地服务程序: EXE 远地服务程序: DLL或EXE =DCOM为什么需要跨越进程、跨越计算机?软件规模持续增加不同EXE程序之间需要交互不同EXE程序可以分布在 不同的计算机上适用于分布式计算环境关键问题:进程空间不同DCOMDCOM内 容跨越进程IDL/MIDL本地服务器的实现远程访问(DCOM)的实现DCOM的特性DCOMDCOM(1)跨越进程每一个EXE文件都将在不同的进程中运行每一个进程都有自己的进程空间 DLL将被映射到连接它们的EXE文件的进程空间 DLL被称为进程中服务器(Inproc server) EXE被称为进程外服务器(Outproc server) DLL提供的构件将接口传给客户 一个接口实际上是一个函数指针数组客户必须能够访问同接口相关联的内存DCOMDCOM对于跨越进程边界的接口 需满足如下要求:一个进程需要能够调用 另外一个进程中的函数 一个进程需要能够将数据传递给 另外一个进程 客户无须关心它所访问的服务器 是DLL还是EXEDCOMDCOM本地过程调用不同进程间通信的方法: DDE 管道 共享内存等 LPCCOM:LPC 基于RPC的单机进程间通信技术 DCOM:RPCDCOMDCOMLPC由操作系统实现客户构件EXEEXELPC进程边界DCOMDCOM编排(Marshal)将函数调用的参数从一个进程的地址空间中传到 另外一个进程的地址空间中 LPC:将参数数据从一个进程的地址空间复制到 另外一个进程的地址空间中 RPC:需要考虑不同机器在数据表示方面的不同支持编排的接口为: IMarshalDCOMDCOM代理/残根DLL(surrogate/stub)客户同一个模仿构件的DLL通信 这个DLL可以为客户完成 参数的编排与LPC调用 这个DLL被称为 代理构件需要另一个DLL 这个DLL为构件完成 参数的反编排 与LPC调用DCOMDCOM客户构件EXEEXELPC进程边界代理残根DLLDLLDCOMDCOM(2)IDL/MIDL 先利用IDL语言编写接口的描述 在利用MIDL编译器生成代理和残根DLL与UUID、RPC类似 IDL是从开发软件基金会OSF的 分布式计算环境(DCE)借用过来的IDL语法与 C、C+相同 COM只利用了IDL的一个子集 并进行了扩展MIDL编译器接收接口的IDL描述 并生成相应的代理和残根DLLDCOMDCOMIDL开发人员可以不知道LPC的细节 但必须知道如何利用IDL描述自己的接口但是 IDL不规范: 存在不一致 文档资料差 缺乏典型的好例子IDL可用于: 生成代理和残根DLL 建立类型库(Type Library)DCOMDCOMIDL例子:import “unknwn.idl“ ; / Interface IX object, uuid(32bb8323-b41b-11cf-a6bb-0080c7b2d682), helpstring(“IX Interface“), pointer_default(unique) interface IX : IUnknown HRESULT FxStringIn(in, string wchar_t* szIn) ; HRESULT FxStringOut(out, string wchar_t* szOut) ; ;DCOMDCOM接口头(属性列表): (1)object: 所定义的接口为一个COM接口 (2)uuid(.):接口的IID (3)helpstring(.):将帮助串放类型库中 (4)pointer_default(unique):如何处理指针使用IDL的目的在于提供足够的信息 以便函数参数可以被调整 因此IDL需要知道如何处理指针 pointer_default的作用在于告诉MIDL 在没有为指针指定其它属性时如何处理指针DCOMDCOMpointer_default具有三个不同的选项: ref: 将指针当成引用对待 该类指针 总是指向一个合法的地址不能为空在调用前后指向相同的内存地址在函数内部不能为其指定别名 unique: 该类指针 可以为空在函数内可以修改其值不能为其指定别名 ptr: 将指针指定为C指针该类指针 可以有别名 可以为空 可以修改其值 MIDL 将使用这些值对它生成的代理及残根代码优化DCOMDCOMIDL中的输入/输出参数利用 in , out这两个参数属性 MIDL可以对代理及残根代码进行进一步的优化对于被标记为 in 的参数 MIDL将知道 仅仅需要将此参数值从客户传递给构件 残根代码不需要回送任何值 对于被标记为 out 的参数 MIDL将知道 该参数仅被用类从构件向客户回送数据 代理不需对输出参数值进行调整也不需将该值传送给构件 可以同时使用两个关键字标记某一参数 输出参数必须为指针 DCOMDCOMIDL中的字符串对数据块进行编排时 必须知道数据块的大小 C+串的长度易于决定 COM对字符串的标准约定是使用Unicode字符:wchar_t也可以使用LOLECHAR 或者 LPOLESTRIDL中的import与C+中的 #include 类似 可以使用任意次 而不会引起重复定义 所有COM及OLE(ActiveX)的标准接口 皆定义于相应的IDL中 一般位于C+编译器的 INCLUDE文件中DCOMDCOMIDL中的 size_is object, uuid(32bb8324-b41b-11cf-a6bb-0080c7b2d682), helpstring(“IY Interface“), pointer_default(unique) interface IY : IUnknown HRESULT FyCount(out long* sizeArray) ;HRESULT FyArrayIn(in long sizeIn, in, size_is(sizeIn) long arrayIn) ;HRESULT FyArrayOut(out, in long* psizeInOut, out, size_is(*psizeInOut) long arrayOut) ; ;DCOMDCOMMIDL编译器foo.idlMidl.exefoo.iifoo_p.cfoo_i.cdlldata.cfoo.defmakefileC编译器 与连接器foo.dll.DCOMDCOMMakefile 中的主要语句:midl /h Iface.h /iid Guids.c /proxy Proxy.c Server.idlServer.dll: $(SERVER_OBJS) Server.def link $(DLL_LINK_FLAGS) $(SERVER_OBJS) libcmtd.lib libcimtd.lib $(LIBS) /DEF:Server.def regsvr32 -s Server.dllServer.exe: $(SERVER_OBJS) $(DIR_SERVER)OutProc.obj Server.res link $(EXE_LINK_FLAGS) $(SERVER_OBJS) $(DIR_SERVER)OutProc.obj Server.res libcmtd.lib libcimtd.lib $(LIBS) user32.lib gdi32.lib Server /RegServerClient.exe : Client.obj Guids.obj Util.obj link $(EXE_LINK_FLAGS) Client.obj Guids.obj Util.obj libcmtd.lib libcimtd.lib $(LIBS)DCOMDCOM(3)本地服务器的实现进程内服务器模式中 DllGetClassObject 创建类厂因为EXE不输出函数 必须给CoGetClassObject提供 获取IClassFactory的方法COM的解决方案是: 维护一个关于被登记类厂的内部表格DCOMDCOM当客户调用CoGetClassObject时 COM首先检查关于类厂的私有表格 以得到与客户请求的CLSID相应的类厂若相应的类厂不在表格中 COM在注册表中查找 并启动相应的EXE 此EXE将完成相应类厂的登记 EXE调用CoRegisterClassObject 完成类厂的登记DCOMDCOMBOOL CFactory:StartFactories() CFactoryData* pStart = const CFactoryData* pEnd =for(CFactoryData* pData = pStart ; pData m_pIClassFactory = NULL ; pData-m_dwRegister = NULL ;/ Create the class factory for this component. IClassFactory* pIFactory = new CFactory(pData) ;/ Register the class factory. DWORD dwRegister ;DCOMDCOMHRESULT hr = :CoRegisterClassObject(*pData-m_pCLSID,static_cast(pIFactory),CLSCTX_LOCAL_SERVER,REGCLS_MULTIPLEUSE,if (FAILED(hr) pIFactory-Release() ; return FALSE ; / Set the data. pData-m_pIClassFactory = pIFactory ; pData-m_dwRegister = dwRegister ; return TRUE ; DCOMDCOM构件注册:CoRegisterClassObject( *pData-m_pCLSID,static_cast(pIFactory),CLSCTX_LOCAL_SERVER,REGCLS_MULTIPLEUSE,m_pCLSID:类标识 pIFactory: 类厂指针 第四个参数:EXE的单个实例 能否支持一个构件的多个实例 REGCLS_SINGLEUSER: 单个实例 则第三个参数为CLSCTX_LOCAL_SERVER REGCLS_MULTI_SEPARATE:多个实例 第三个参数可以为CLSCTX_LOCAL_SERVER 或者 CLSCTX_LOCAL_SERVER| CLSCTX_INPROC_SERVERDCOMDCOMCoRegisterClassObject( *pData-m_pCLSID,static_cast(pIFactory),CLSCTX_LOCAL_SERVER,REGCLS_MULTIPLEUSE,与CoRegisterClassObject( *pData-m_pCLSID,static_cast(pIFactory),CLSCTX_LOCAL_SERVER| CLSCTX_INPROC_SERVER,REGCLS_MULTI_SEPARATE,是等价的DCOMDCOM(4)远程访问的实现前述的本地服务器可以是远地服务器 即 不需要对CLIENT.EXE或SERVER.EXE 进行任何修改需要系统的支持: Windows NT4.0 或者 DCOM for Windows95它们需要DCOM配置工具 DCOMC
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号