没怎么翻译过,公司要求,所以翻译了下,不知道效果如何!!贴出来,让大家指正!
Microsoft rpc 概述
微软RPC是一个分布式计算的编程模型,RPC的目标是提供一个透明的通信,以便让客户端看起来能直接的和服务器进行通信。微软的RPC实现符合开放式软件基于(OSF)的分布式计算环境的RPC。
你可以配置RPC成使用一个或者多个传输,一个或者多个名字服务,和一个或多个安全服务。这些提供者的接口被RPC所处理。微软的RPC被设计成能和多个提供者协作,因此,你能够选择对于你来说最佳的网络。传输层负责跨网络传输数据。名字服务器获取一个对象名并且对他进行网络定位,例如:名字对象(moniker)。安全服务器提供给应用程序对指定用户和或组的可选的拒绝访问。对于应用的安全,详情见“借口设计规则”。
对于RPC运行时库,微软RPC包含了IDL和他的编译器。虽然IDL文件是一RPC标准的一部分。微软还是加强了他,并扩展他的功能使之支持COM自定义接口。MIDL编译器使用IDL文件描述你的自定义接口去生成一些文件,这些文件在下节的构建和注册代理DLL将会讨论。
COM接口设计规则
这节提供了一个简短的接口设计规则和向导的总结。一些规则对于COM是特有的,但是另外一些是被IDL强加的限制。MIDL,更细节的COM接口设计,请看IDL文件解析。
通过定义,一个实现了IUnknown接口或者从 IUnknown接口派生的对象才叫COM对象。另外,以下规则应用于所有在COM对象上实现的接口。
他必须有一个唯一的接口表示(IID)。
他必须是不可变的。一旦被创建和发布,他的定义部分不能改变。
所有的接口方法必须返回一个HRESULT以便处理远程进程的系统部分能够报告RPC错误。
所有的字符串参数必须是UNICODE。
你的数据必须是可被远程化的。如果你不能把一个数据类型转化成一个可远程化的类型。你将必须创建你自己的列集和散列的例程。所以,LPVOID,或者VOID*在远程机器上没有任何意义。如果必要,使用一个指向IUnknown的指针。
COM对象内通信
COM被设计成允许客户端和对象进行透明的通信,不考虑这些对象是运行在相同的进程,相同的机器,或者不同的机器上。这为所有的对象类型,包括客户端和对象服务器,提供了单一的编程模型。
从一个客户端的视角来看,所有的对象都是通过接口指针来访问的。这个指针必定是进程内的。事实上,任何对于一个接口函数的调用总是先到达进程内的代码块。如果对象是进程内的,调用请求直接到达。没有系统内的基础代码来辅助。如果对象是进程外的。调用请求首先到达代理对象(被COM提供或者被对象提供),代理打包所有的调用参数(包括任何借口指针)和产生合适的RPC到对象所在的其他进程或者其他机器上。这个打包指针来跨进程边界的传输过程叫做列集。
从一个服务器的视角来看,所有的对于某个对象接口函数的调用通过指向那个接口的指针来做到。那个指针仅仅只有单个进程的上下文。而且调用者必须总是在进程内的代码中。如果对象在进程内,调用者就是客户端本身。否则,调用者是一个存根对象(由COM或者对象本身提供)存根接受一个来自客户端进程中的代理RPC调用。散列参数,然后调用合适的接口,从客户端和服务器端得视角来看,他们总是用一些进程内的代码来直接的通信。
COM提供了一个列集的实现。参考为标准的列集。这个实现和大部分对象工作的非常好,而且还极大的降低了编程的要求,使列集的过程高度透明。
接口和COM处理实现的明确隔离的透明性,在某种程度上,达到了非常好的效果。尽管如此,接口的设计从客户的视角只是集中注意力在他的功能上,有时候会导致,设计的决策和跨网络接口的实现的高效性相冲突。像这种情况,我们所需要的不单纯是处理的透明性,而是“进程完全透明,除非你需要去关心这些细节”,COM提供了这种能力,他通过允许对象实现者自己去支持自定义的列集。标准的列集事实上是自定义列集的一个实例。当对象不要求自定义列集的时候,标准的列集是被默认实现使用的。
你可以实现自定义的列集允许对象被用于跨网络的时候可以采取不同的行为。而不是胜任本地的访问。他对客户端是完全透明的。这种结构使得设计客户/对象接口不需要考虑网络执行细节成为可能。而且,定址网络的执行细节而不需要扰乱建立的设计。
COM不需要指定组建被构建的方式。他指定了他们交互的方式。COM把关心组件的内部结构留给了编程语言和开发环境。相反,编程环境没有一套和外部应用对象工作的标准。微软的VC++,例如:他工作的非常的好对于操纵应用内部的对象。但是没有提供应用外部对象的支持。总的来说,所有的其他的语言在这方面也是一样的。因此,提供网络范围内的协作能力。COM,通过语言独立的接口,弥补了编程语言所做不到得东西。
Vtbl结构的双向性意味着函数指针表里面的指针不需要指向正真的对象的实现。这是进程透明性的核心。
对于进程内的服务器,对象不直接载入到客户进程里面。表里面的函数指针直接指向实际的实现。这种情况,来自客户端的对接口方法的调用直接转移执行控制到实际的实现。尽管如此,这种形式 不能完全在本地工作。单独考虑远程的情况,因为指针指向的内存不能夸进程共享。但是,客户端必须能够像是在调用实际的实现一样来调用接口方法。因此,客户端通过调用的方式统一的转移控制到某些对象的方法里面。
客户总是能够在进程内对象里面调用接口方法。如果实际的对象在本地(其他进程里面)或者远程的机器上。那么这个调用必须被传递给代理对象。他来做一个对实际对象的RPC调用。
因此,方法是如何被执行的。答案是。无论什么时候,有进程外接口的调用,那么每个接口的方法都被代理对象所实现。代理对象是一个进程内对象,他的行为基于被调用的那个对象。这个代理对象知道实际的对象到底是在本机还是在远端机器上。
代理对象打包函数的参数到一些数据包里面,然后产生一个RPC调用到本机或者远程对象上。这个包被服务器进程的存根对象获取。然后解包参数,然后把调用分配到实际的方法的实现上。当这个函数返回了。存根打包所有的出参数和返回值。然后把结果发回个代理对象。代理对象解包他们,然后,把他们返回给原始的客户端。
因此,客户端和服务器的彼此对话,就好像在同一进程里面一样。所有来自客户端得调用和到服务器的调用在某种程度上,是进程内的。由于vtbl结构允许一些代理,比如COM,去拦截所有的函数调用和函数的返回值。如果有必要,代理会重定向这些调用到RPC调用。虽然进程内的调用比进程外的调用更快,但是进程的区别对于服务器和客户端都是完全透明的。
COM列集细节
如果使用标准的列集,COM处理这一节描述的所有细节。这节提供给这些对列集细节的编程新手和对底层信息感兴趣的人。列集是打包和解包参数的过程,因此一个RPC可能出现列集和散列。
不同的参数类型采取不同的列集方式。例如:列集一个整型参数仅仅涉及到简单的拷贝值到消息缓冲区。(尽管这种情况简单,任然要考虑跨机器的字节序的处理),列集一个数组,是一个更复杂的过程。数据的成员以一种指定的顺序来拷贝,以便另一边能够精确的重构这个数组。当指针被列集,指针所指向的数据按以下规则拷贝和转换,为了处理结构体中指针嵌套的情况。特有的函数去处理各种参数类型的列集。
标准的列集,对于接口来说,代理和存根是系统范围内的资源,他们通过标准的协议来和频道交互。标准的列集既能够被标准COM定义的接口来使用,也能够被自定义接口来使用。按照以下规则:
大部分的COM接口,代理和存根对于标准的列集是进程内组建对象,他们从Ole32.dll中的COM所提供的系统DLL中被载入。
如果是自定义接口,标准列集的代理和存根被接口设计者所产生,通常是用MIDL.这种代理和存根在注册表中被静态配置。因此任何可能的客户都可以使用自定义接口跨进程边界。这种代理和存根通过系统注册表的路径找到得DLL所载入。他们使用接口ID为自定义接口列集。
为自定义接口使用MIDL产生代理和存根 作为一种可选的方案,类型库可以被产生来代替而且系统提供的类型库驱动的列集引擎将列集接口。
相对于标准列集,一个接口(标准或者自定义)能够使用自定义列集。在自定义列集的时候,对象为他支持的每个接口动态实现了运行时的代理。对于一个给定的接口,对象可以选择COM提供的标准列集或者自定义列集。选择被接口基于的对象所确定。对于给定的接口,一旦选择被被确定。在他的生命周期内,他会一直有作用。尽管如此,一个对象的接口可以使用自定义列集当其他的在使用标准列集的时候。
自定义列集对于实现的对象来说是固有的。他使用对象实现的代理在运行时按要求提供给系统。实现自定义接口的对象必须实现IMarshal接口。支持标准列集的对象不需要。
如果你决定写一个自定义接口,你必须提供一个列集支持,通常,你将为你的设计的接口提供一个标准的列集DLL。你也可以使用平台SDK CD中的工具来创建代理和存根代码和代理存根DLL。可选的,你也可以使用这些工具创建类型库,COM将会使用它做数据驱动的列集。
对于一个客户端,在另外一个进程调用一个对象的接口方法会牵扯到多个组件的相互协作。标准的代理只是接口指定代码(存在于客户进程地址空间中,准备接口参数的传输)中的一部分,他打包,列集他们以一种能够被接收进程重建和理解的方式。标准的存根,也是接口代码的一部分,存在于服务器进程地址空间,逆向代理的工作。存根解包,散列,发送参数,传递参数给对象的应用,他也打包返回信息给客户端。
COM代理
代理存在于调用进程的地址空间中,为远端的对象扮演代理的角色。从调用对象的角度来看,代理是一个对象。通常,代理的角色是去打包对象接口方法的参数。代理打包参数到一个消息缓冲区,然后传递缓冲到频道中。频道处理进程之间的传输。代理被实现为一个聚合的,或者包容的对象。他包含了一个系统提供的管理部件,叫做代理管理器和一个或多个接口指定的组件叫做接口代理。接口代理的数量等于对象暴露给特定客户端的接口的数量。对于客户端服从组件对象模型,代理看起来是真正的对象。
每个接口代理是一个为对象的一个接口实现了列集代码的组件对象。代理代表了这个对象,代理为其提供了列集代码。每个代理也实现了IRpcProxyBuffer接口。虽然被代理代表的对象接口是公共的,但是 IRpcProxyBuffer的实现是私有的,而且在代理的内部使用。代理管理器跟踪接口代理而且包含了用于聚合的IUnknown接口控制的实现。每个接口代理能够存在于 单独的DLL中,当他支持的接口被实例化给客户端的时候被载入。
COM存根
存根,像代理一样,由一个或多个接口部件和一个管理器组成。每个接口存根提供了代码去散列参数和调用对象支持的接口之一的代码。每个存根也提供了一个接口用于内部的通信。存根管理器跟踪可用的接口存根。
以下是存根和代理的区别:
最重要的不同是存根在对象地址空间中代表客户端
存根没有被实现为一个聚合对象,因为没有要求将客户端视为一个单个的单元。每个在存根里面的部件是一个单独的组件。
接口存根是私有的而不是共有的
接口存根实现了IRpcStubBuffer而不是IRpcProxyBuffer
取代打包参数被列集,存根解包他们,当他们被列集后。然后打包回应包。
COM通道
通道负责在客户和对象之间夸进程传输所有的消息。通道被设计成和不同的频道类型透明的工作。适合于OSF(开放式软件基金)DCE(分布式计算环境),而且支持单线程和多线程的应用。
RPC模型
远程过程调用(RPC)是为C/C++编程语言设计去满足开发者在下一代Windows家族操作系统上软件开发的需求而设计的。
RPC是一个强有力的,健壮的,高效的和安全的进程间通信的机制。这种机制使数据具有在不同的进程间进行交换和调用的能力。不同的进程可以是在相同的机器上,或本地网络上,或跨因特网。这节解释了RPC编程模型和能够用RPC实现的分布式系统模型。
RPC完全支持64位的Windows.在windows xp中,有三种进程:本地32位进程。本地64位进程,和运行在64位系统上的32位处理器模拟层的32位进程。使用RPC,开发者可以透明的和不同的进程进行通信。RPC 自动的管理进程背后的不同性。
RPC最初被发展成一个对OSF RPC的一个扩展。除了他的一些高级特性,RPC和其他厂商的OSF RPC的实现是可互操作的。
这节提供了RPC 组件和他的操作的总揽。以下是具体的信息:
编程模型
分布式系统模型
RPC如何工作
RPC 微软组件
RPC如何工作
原理图:
RPC工具让用户看起来像是客户端直接调用远端服务器中的过程的。客户端和服务器端每个都有他们自己的地址空间。也就是,他们都有自己的内存资源,可以被过程用于分配数据的存储空间。以上的图标解释了RPC的结构。
根据图示,客户应用调用本地存根过程来取代相应的实际的实现代码过程。存根被编译和链接到客户的应用程序。代替了包含实际代码的远程过程的实现。客户存根代码主要做以下工作:
接受来自用户地址空间的参数
根据需要将参数转换成NDR格式在网络上传输
在RPC客户端运行时库中调用函数去发送请求和参数到服务器。
服务器做以下步骤来进行调用远程过程。
1. 服务器RPC运行时库接收请求,然后调用服务器存根过程。
2. 服务器存根接受来自网络缓冲的参数然后把他们从网络传输的格式转换成服务器需要的格式。
3. 服务器存根调用实际的服务器的过程。
远程过程然后运行,可能有出参数和返回值。当远程过程完成了,一系列的步骤将数据返回给客户端。
1. 远程过程返回数据给服务器存根。
2. 服务器存根转换出参数为网络传输的格式,然后把他们返回给RPC运行时库函数。
3. 服务器端得RPC运行时库函数将数据通过网络传输给客户端的电脑。
客户端接收到网络的数据完成处理,然后返回给调用的函数。
1. 客户端RPC运行时库接收远程过程的返回值然后返回给客户的存根。
2. 客户存根将NDR格式的数据转换成客户端需要的格式。存根写数据到客户的内存然后返回结果给客户端的调用程序。
3. 调用过程的执行就好像这个过程就在同一台机器一样。
对于微软的windows,运行时库被提供成两个部分,一个引入库,他连接了应用和RPC运行时库。还有一个实现,叫做动态链接库。
连接客户端和服务器
为了通信,客户端和服务器端必须建立一个跨网络的通信会话。一旦建立连接客户端可以调用服务器端得过程,就像在本地调用一样。
这节提供了一个如何建立C/S之间的RPC连接的概念总揽。没有提供关于这个主题的深度讨论。所有这节的概念在以后章节中呈现。
管道
管道类型构造器是一个高效的传输大量数据和任意数据量的机制。通过管道,RPC在运行时处理实际的数据传输,消除了重复RPC的开销。
客户端调用一个有管道参数的远程过程后,客户端和服务器端进入循环去传输数据。数据可以在客户端和服务器端产生。两种方式的任意一种情况,数据的多少没有必要提前知道。数据可以被增量的产生或消耗。当数据在循环传输中的时候,服务器端调用存根例程载入或者卸载缓冲数据。客户端调用编程人员定义的过程去分配缓冲,载入数据到缓冲或从缓存卸载数据。
绑定和句柄
这节解释了在客户和服务器程序中创建和使用绑定和绑定句柄。也讨论了C/S上下文和上下文句柄。信息被分成以下两个部分:
绑定句柄
上下文句柄
绑定句柄
绑定是在客户程序和服务器程序之间建立逻辑连接的过程。构成客户端和服务器端绑定信息的结构叫绑定句柄。
绑定句柄类似fopen函数返回的文件句柄,或者CreateWindow返回的窗口句柄。
有了这些句柄,你的应用程序不能直接访问和操作绑定句柄中的信息。绑定句柄数据结构中的信息仅对RPC运行时库来说是可行的。你提供句柄,运行时库来访问和合适操作的数据。
异步RPC
异步RPC是一个微软对传统RPC模型的扩展,异步RPC把远程过程调用和他的返回值隔离开来,不像传统RPC受到以下的限制,同步RPC:
来自单线程客户端的多个外部的调用。在传统的RPC模型里面,客户端的远程调用将会被阻塞,直到调用返回。这种情况不允许客户端有多个并发调用,之后让线程去做其他的事情。
减慢或延迟客户端。一个减缓产生数据的客户端可能想进行一次用初始化数据调用RPC然后提供附加的数据作为他产生的数据。这个用同步RPC时不可能做到的。
减慢或延迟服务器。RPC的完成将会占用线程任务的很长时间。而异步RPC,服务器可以开始单独的(异步)操作去处理请求和发送回应。当可行的时候,服务器也可以增量的发送回应,而没有必要去占用分发线程的太多时间。通过异步RPC的客户端,可以组织慢的服务器对客户应用的影响。
传输大量的数据。在客户端和服务器端传输大量的数据,特别是在速度慢的链接上,既占用了客户端的线程传输时间,也占用服务器端的管理线程的时间。通过异步RPC和管道,数据的传输可以使增量的,不需要阻塞客户端和服务端去执行其他的任务。
你可以利用异步RPC机制通过将函数声明为[async]属性。因为这种声明是在属性配置文件中(ACF),你没有必要在IDL文件做任何改动。异步RPC对wire protocol 没有效果。这意味着同步和异步客户端都能和异步服务器通信。
RPC消息队列
消息队列让用户跨网络和系统进行通信,而不必考虑通信应用程序和系统的状态。应用程序发送和接受消息通过MSMQ维护的消息队列来实现。即使客户或服务器应用程序没有运行了,消息队列也会一直起作用。消息队列提供的了以下功能:
异步消息。通过MSMQ的一部消息队列,客户端应用程序可以发送一个消息到服务器,然后立即返回,即使目标机器或服务器没有回应。
可靠的消息投递。当一个应用通过MSMQ发送一个消息,即使目标应用程序没有运行,或网络和系统是离线的,这个消息也会到达目的地。
路由和动态配置。MSMQ在各种混杂的网络提供了一个灵活的路由。网络的配置能够被动态的改变而不需要对 网络和系统做重大的改变。
无连接消息。应用使用MSMQ不和目标应用建立直接的会话。
安全。MSMQ提供了一个基于windows 安全和加密API对每个加密和数字签名的安全通信机制。
有优先级别的消息。MSMQ跨网络传输消息基于优先级,为紧迫的应用程序提供更快的通信。
微软RPC扩展了OSF-DCE模型。这种功能通过IRPCOptions接口对于RPC应用,COM应用都是很便利的。