1、DCOM
COM的进程透明特性表现在组件对象和客户程序即可以拥有各自的进程空间,也可以共享同一个进程空间,COM负责把客户的调用正确传到组件对象中,并保证参数传递的正确性。组件对象和客户代码不必考虑调用传递的细节,只要按照一般的函数调用的方式实现即可。如果进一步拓展进程透明特性,考虑组件对象与客户程序运行在不同计算机上的情形,把进程透明性拓展为位置透明性,形成分布式组件对象模型,简称为DCOM。
DCOM是COM的扩展,它可以支持不同计算机上组件对象与客户程序之间或者组件对象之间的相互通信,这些计算机可以在局域网内、广域网上、 Internet上。对于客户程序而言,组件程序所处的位置是透明的,我们不必编写任何处理远程调用的代码,因此,DCOM也是COM的无缝扩展。 DCOM处理了底层网络协议的所有细节。
2、从COM转向DCOM
进程内组件与客户程序之间的通信过程比较简单。本地进程外组件与客户程序之间的通信并不是直接进行的,而是用到了操作系统支持的一些跨进程通信方法。
DCOM只是简单地把本地跨进程通信用一个网络协议传输过程来代替,只是中间数据传递的路线更长一些。当然,网络通信比单机系统环境下的跨进程通信要脆弱得多,所以为了保证协作过程的可靠性以及程序对异常事件的应变能力,客户程序和组件程序需要考虑更多的细节。
3、DCOM对象的定位
客户程序调用COM库的基础创建函数(比如CoGetClassObject)创建远程组件对象需要知道远程机器名和对象CLSID。
有两种方法可以得到远程对象的机器名信息:一是在创建函数的参数中指定COSERVERINFO结构,二是使用DCOM配置工具指定远程机器名。
COM库的创建函数得到了远程对象的位置信息后,再把对象创建的任务交给SCM,由SCM通过RPC与远程机器进行通信。SCM(程序名为 Rpcss.exe)也是COM库的一部分,但它是一个单独的进程。SCM负责创建新的COM对象,也负责建立组件对象与客户程序之间的连接。如果要创建远程对象,它会通过RPC调用远程机器上的SCM,由远程机器上的SCM启动组件进程,并创建组件对象,然后返回到客户机器。
当然,远程组件对象被创建之后,它在返回到客户机器的途中,还要经过列集和散集的处理,包括创建代理对象和装载存根代码等,这些处理与本地进程外组件对象的处理完全一致。一旦组件对象被创建完成之后,客户与组件之间的通信不再经过SCM,而是直接通过代理对象和存根对象以及COM库提供的底层传输机制来完成。
4、列集与散集
列集与散集是实现COM组件对象跨进程特性的关键技术,它包括标准列集法和自定义列集法。同样的技术也适用于DCOM组件对象与客户程序之间的通信,两者的区别在于列集数据包的传递方式有所不同,对于本地组件对象使用LPC传递,而对于DCOM组件对象使用RPC传递。
DCOM提供了一套复杂的列集和散集机制,它建立在RPC的基础上。由于RPC被定义为DCE(分布式计算系统)标准的一部分,而DCE RPC定义了所有常用数据类型的数据表达方式,即网络数据表示法(NDR,network data representation)。为了使存根代码和代理对象能够正确地对参数和返回结果进行列集和散集,它们应该使用一致的数据表示法NDR,以便在不同的操作系统环境下也能够远程调用。
5、对象RPC
DCOM协议也被称为对象RPC(ORPC,object remote procedure call),它建立在DCE RPC协议的基础上,可用于各种基于组件的分布式系统。ORPC建立了一套面向对象的远程调用规范,指定了如何在网络上进行调用、对对象的引用如何表示和如何维护。ORPC协议已经被作为Internet草案递交到IETF(Internet Engineering Task Force , Internet 工程部)。
在Internet或Intranet网络环境下,ORPC仍使用标准的RPC数据包,附加上专用于DCOM的一些信息――接口指针标识符(IPID,interface point identifier)、版本信息和扩展信息――作为调用和返回的附加参数进行传送,其中IPID表示调用被处理的远程机器上特定对象的特定接口。 DCOM客户程序必须周期性地“pinging”远程机器上的对象,以便保证客户与对象一直处于连接状态。
6、DCOM特性
DCOM可以作为分布式应用系统的基本架构,客户程序与DCOM组件对象之间形成了客户/服务器关系,进一步可构成多层软件模型。DCOM组件具有COM 组件的一些基本特性,包括重用性、语言无关性等。而位置透明性 是DCOM的一个基本特性。DCOM的其他特性如下:
(1)可伸缩性。一方面,DCOM利用操作系统本身的可伸缩性;另一方面,DCOM提供了灵活的配置方案,允许不同的组件对象允许在不同的服务器上,DCOM的位置透明性保证了这种变化可以不必修改组件源程序。
(2)可配置性。安装和管理是分布式软件系统的两个重要环节。DCOM提供了一个图形界面的配置工具程序(DCOMCNFG.EXE),可使客户程序和组件程序在不改变代码的情况下适应不同的网络环境。
(3)安全性。DCOM使用了Windows NT提供的可扩展安全性框架,在非NT平台上实现的DCOM也包括了一个与NT兼容的安全提供器。DCOM实现的安全性分为访问安全性和激活安全性,访问安全性指定那些用户可以调用组件对象,激发安全性指定哪些用户可以在一个新进程中创建新的对象。
(4)协议无关性。
(5)平台独立性
7、对象激活
激活(activation)一个组件对象包括两种情形:一是创建新的组件对象,二是建立已有组件对象与客户之间的连接。
COM扩展到DCOM之后,远程对象的创建过程有所不同。为了标识一个远程对象,仅仅提供一个128位的GUID还不够,还必须提供远程对象所在的机器名,也称为远程服务器名“RemoteServerName”。
(1)创建DCOM组件方法一
通过DCOM配置工具指定远程服务器名,这种方式使得DCOM组件具有位置透明性。在Windows系统平台上,远程服务器名字RemoteServerName值被保存在系统注册表HKEY_CLASSES_ROOT\APPID键下。
从CLSID和AppID键的结构可以看出,每个AppID可用于多个组件对象,通常它代表了由多个CLSID共享的进程,该进程中的所有对象共享同样的配置信息,包括远程服务器名以及安全信息。在DCOM中引入AppID概念可以避免太多的注册表关键字。
(2)创建DCOM组件方法二
用第一种方法并不是总能满足应用的要求,有些应用要求在程序运行过程中控制要连接的服务器,比如多人游戏程序、网络远程管理工具等。对于这样的应用,DCOM允许在创建函数中指定远程服务器名字。可以指定远程服务器名字的创建函数:CoCreateInstanceEx、 CoGetClassObject、CoGetInstanceFromFile、CoGetInstanceFromeIStorage。
在程序中指定服务器名字的另外一个功能是实现分布式应用系统的动态负载平衡。目前DCOM还很难以实现自动负载平衡特性,但我们可以建立一个分派服务组件对象,所有的客户都创建指定机器上的分派服务组件对象,由它创建另一个真正实现应用功能的远程对象,在把此远程对象返回给客户程序,以后客户程序不再使用分派服务组件对象,而直接调用远程对象。而分派服务组件对象可以根据当前的负载状态,从一组服务器中选择负载最轻的服务器作为目标,创建远程对象。
8、远程创建进程内组件:代理进程(surrogate)
为了远程运行进程内组件即DLL组件,要求在远程机器上有代理进程(surrogate process)。除了可以远程启动进程内组件之外,代理进程还提供了下面的特性:
l 进程内组件程序中的严重错误只影响代理进程,不会使客户进程崩溃;
l 一个代理进程可以同时为多个客户提供服务;
l 客户可以保护自己避免靠不住的组件程序代码,只访问组件程序提供的服务;
l 在代理进程中运行进程内服务可使DLL享有代理进程的安全性。
Windows引进了缺省的代理进程,以及编写自定义代理进程的协议规范。缺省实现的代理进程是一个混合线程模型、伪COM服务程序。当多个DLL组件被装入到单个代理进程时,该进程按照注册表中指定的线程模型对每个DLL组件对象进行实例化。如果一个DLL组件对象支持两种线程模型,则COM选择自由线程模型。COM即可以控制DLL组件程序的卸载,也可以终止代理进程。
如果一个进程内组件满足下列条件,则它将被装入代理进程:
l 系统注册表中,在组件对象的CLSID关键字下必须要指定AppID值,以及对应的AppID关键字;
l 客户程序在创建对象实例时,必须设置CLSTX_LOCAL_SERVER标志;
l 组件对象的CLSID关键字下不指定LocalServer32、LocalServer、LocalService值;
l 组件对象的CLSID关键字包含InProvServer32子键;
l 在InProcServer32子键中指定的DLL文件必须存在;
l 组件对象对应的AppID键下指定DllSurrogate值。
如果组件对象的CLSID键下的LocalServer、LocalServer32或LocalService值指示了EXE的存在,则EXE程序将被优先执行,COM不再启动代理程序。
9、利用名字对象(moniker)连接到远程对象实例
通常COM对象实例是不可相互替代到,或者说不可相互交换的。它通过自己特有的状态区别于同一类的其他对象实例。
在第8章中介绍的COM命名和绑定机制对于远程对象同样适用。
10、连接管理——远程对象生存期的控制
COM控制对象的生存期最基本的机制是引用计数,利用IUnknown的AddRef和Release成员函数控制对象的生存期。DCOM优化了远程对象的AddRef和Release的调用。优化过程使用了OXID(object exporter identifier ,对象管理标识符)对象。OXID是一个64位值,通过OXID可以把RPC串绑定调用到它们的目标IPID。但是,在执行调用之前,调用进程必须把 OXID转译成为底层RPC可以解释的一组绑定。
在每台支持DCOM的机器上,都有一个被称为OXID解析器(OXID Resolver)的服务,它负责向客户提供用于连接到OXID的RPC串绑定信息,也负责接收远程发来的“pinging”信息。OXID解析器之间通过RPC进行通信,它实现了RPC接口IOXIDResolver(不是COM接口)。
11、连接管理——pinging机制
如果不考虑客户进程可能会非正常终止,则利用远程引用计数控制对象生存期已经足够了。为了检测客户程序是否非正常终止,DCOM提供了一种简单的方法 “pinging”。在现在实现的DCOM版本中,pingPeriod=2(分)且numPingsToTimeOut=3,这些值不能被改变。
12、连接管理——连接点管理
许多实际的分布式应用都需要在两个对象之间进行双向通信。由于DCOM是对COM的无缝扩展,在第6章中介绍的COM提供的连接点机制同样适用于远程对象的情形。
13、连接管理——连接传递
用分派服务组件对象来实现分布式应用的负载平衡特性实际上用到了连接传递特性。
连接传递不等于远程对象创建的传递,DCOM不支持位置透明方式下对象创建的传递过程,但可以利用连接传递特性,通过程序控制服务器名字的方式实现远程对象创建的传递。
14、并发管理——线程模型
COM本身并没有线程模型,可以认为COM借用了Windows操作系统提供的线程模型,Win32程序设计模型把线程分成UI线程和辅助线程,相对应地,COM把线程分成套间线程和自由线程。套间线程使用CoInitialize API函数执行COM库的初始化,COM在套间线程内部创建了一个隐藏的窗口,此窗口的窗口过程函数负责把客户对套间中的组件对象的调用发送到正确的成员函数中。
15、并发管理——消息过滤器
COM和DCOM的线程模型使我们了解到了客户程序与组件对象调用过程中的线程切换,但调用可能会阻塞程序,甚至使得客户程序无法正常进行。为此,COM提供了消息过滤机制,它既可用于客户程序,也可用于组件程序,允许它们对于入调用和出调用有所选择。
COM把调用分为三类:第一种是同步调用,这是最常见的调用类型,客户调用组件对象,一直等到对象执行完所有功能后再返回;第二种是异步调用,客户调用组件对象,但不等到对象执行完功能就马上返回,以后对象通过出接口通知客户程序,这也就是我们在第6章介绍的可连接对象机制;第三种为输入同步调用,被调用对象必须在放弃控制之前返回,以便保证用户界面不受影响,也就是说,在调用执行过程中,对象不能调用任何可能会进入消息循环的函数。
16、DCOM安全模型
DCOM安全性建立在底层安全提供器基础上,有些操作系统可以支持多个安全提供器,DCOM和RPC也可以同时支持多个安全提供器。所有的安全提供器有一个共同点,它们提供了一种表示安全角色(一般为用户账号)的方法、一种鉴定安全角色(一般通过口令或私有钥匙)的方法,以及管理安全角色和其鉴定数据的一套机制。
17、DCOM安全模型——安全性策略
(1)访问安全性和激发安全性。
(2)对象的安全身份。
(3)保护数据。
(4)鉴定级别。
(5)模仿级别。
18、DCOM安全模型——安全性配置
DCOM提供了多种保护应用程序的方法,一方面,DCOM可以强制使用安全性而不用任何对象或对象的客户程序做任何工作,对象的安全性设置可以在外部配置并且DCOM会自动强制使用。另一方面,DCOM把它完整的安全性结构暴露给开发者,因而客户和对象都可以通过程序控制其安全策略。