使用远程过程调用
远程过程调用模型是一般性的。程序员可以选择下列方式中的任何一个来使用远程过程模式:
- 只作为一种程序的规约技术。为此,程序员参照RPC模型,将客户和服务器间的所有交互要么指明为过程调用,要么指明为返回。过程的参数指明了客户和服务器间所传递的数据。在设计客户和服务器时,程序员可以忽略过程的结构,但是利用过程的规约来验证最终系统的正确性
- 即作为一种程序的规约由作为程序设计的一种抽象。为实现这种方法,在设计应用程序和通信协议时,要想到远程过程调用。对所设计的通信协议的每个报文,都紧密的对应于远程过程调用
- 为概念性设计和实现中的明确性。为在实现中包含RPC,程序员设计广义的RPC报文格式和将控制传递给远程过程的协议。在客户和服务之间传递数据时,程序员将严格的遵照过程的规约。程序使用一种标准的外部数据表示来对参数进行编码,并且严格的按照设计中所给出的数据类型规约来进行。它调用标准的库例程来完成数据的计算机本地表示和数据在网络中穿越时所使用的的外部表示之间的转换
- 通过白手起家构造所有的软件来设计和实现。程序员构建一个解决某个问题的传统应用程序,接着,将这个程序沿着过程边界划分为几片,再将这些程序片转移到各台独立的机器中。在调用远程过程时,程序使用ONC RPC报文格式(包括XDR数据表示)和ONC RPC程序编号体制。程序员只按照RPC的规约来构建程序的实现,使用ONC RPC端口映射器将远程程序号绑定到对应的协议端口山。
- 使用标准的库来设计和实现。程序员构建应用程序并用ONC RPC规约将它划分为几片,但尽可能的依赖于现有的RPC库例程。比如,程序员使用库例程向端口映射器注册,使用库例程构造和发送远程过程调用,以及使用它们构造应答
- 自动实现。程序员完全遵照ONC RPC规约,使用程序自动生成工具帮助程序员自动构造客户和服务器所必须的一些程序片段,以及调用RPC库例程,执行比如向端口映射器注册、构造一个报文、将调用分派到远程程序中适当的远程过程等任务。
支持RPC的编程工具
ONC PRC的实现为那些希望避免不必要编程的程序员提供了极大的帮助。帮助源于下面四种形式
- XDR库例程,它们将各自的数据条目从内部形式转换为XDR标准外部表示
- XDR库例程,它们将用于定义RPC报文的复杂数据聚合体(比如数组和结构)进行格式化
- RPC运行事件库例程,这些例程允许程序调用远程过程、向端口映射器注册服务、将传入调用分派到远程程序中正确的远程过程
- 程序生成工具(也叫做stub生成器),它产生构建使用RPC分布式程序所需要的很多C的源文件
RPC允许事件库具有一些过程,它们提供了RPC所需要的多数功能。比如,过程call rpc向服务器发送RPC报文,它具有如下形式:
callrpc(host, prog, progver, procnum, inproc, in, outproc, out);
- 参数host指向一个字符串,该字符串含有机器名,远程过程在这台机器上执行
- 参数prog、progver、procnum分别标识了远程程序号、所使用的程序的版本以及远程过程号
- 参数inproc给出了本地过程的地址,可以调用该过程把参数整理到RPC报文中
- 参数in给出了给远程过程参数的地址
- 参数outproc给出了本地过程的地址,可以调用该过程对结构进行
- 参数out给出了存储器地址,过程执行结果放在这里
尽管callrpc已处理了发送RPC报文所要求的许多杂务,ONC RPC库例程还包含许多其他的过程。比如:
handle = clnt_create(host, prog, vers, proto);
它创建了一个整数标识符,可以用于发送RPC报文。RPC将这个整数标识符称为句柄(handle)。给clnt_create的参数指明了远程主机的名字、在该主机上的远程程序的名字、该程序的版本号,还有一个协议(TCP/UDP)
这个库还包括创建、存储和处理鉴别信息的例程,比如:
authunix_create(host, uid, gid, len, aup_gids);
它为某个给定主机上的某个给定用户创建了一个鉴别句柄。它的参数指明了远程主机、用户的登录标识符和主组标识符、还有用户所属的一些组(aup_gids),参数len指明了在这个组中的条目的数目
远程过程
将程序划分为本地过程和远程过程
为理解RPC编程工具是如何工作的,必须先理解程序是怎么划分为本地过程和远程过程的。对于传统应用中的过程调用:
每个过程都有一组形参,每此调用这个过程时参数的个数、参数类型必须和目标过程匹配。换句话说,参数定义了调用过程和被调用过程之间的接口
为参数增加代码
将一个或者多个过程转移到远程机器上要求程序员在过程调用和远程过程之间增加代码。在客户一端,新代码必须整理参数,将它们转换成独立于机器的表示,创建RPC报文,把报文发送给远程程序,接着等待结构,将最终的结构转换回客户的本地表示。在服务器一端,新代码必须接受传入RPC请求,将参数转换成服务器的本地数据表示,将报文分派给合适的过程,还要将响应先转成独立于机器的数据表示,然后生成应答报文,并发回给客户端
stub过程
为实现RPC而加入到程序中的附加过程称为stub过程。理解stub过程的最简单方法是设想一些常规的程序,它被分隔成两个程序,一个已有的过程被转移到远程机器中。在远程过程(服务器)一端,stub过程取代了调用者。这两个stub实现了远程过程调用所需要的所有通信,它使得原来的调用和被调用过程都必须更改
多个远程过程和分派
上图给出了RPC的简图,因为它只展示了远程过程调用。在实际中,服务器进程往往在远程程序中包含有多个远程过程。每个RPC调用都由一个报文构成,该报文标识某个指明的远程过程。当RPC报文到达时,服务器使用报文中的远程过程号将这个调用分派给正确的过程。如下图:
上图说明了RPC是如何与传统的客户-服务器实现相关联的。该远程程序由单个服务器进程构成,在任何报文到达之前,它必须已经在运行。一个远程过程调用可以来自任何客户,它必须指明该服务器机器的地址、在该机器上的远程程序号以及要调用的远程过程。服务器程序由分派器例程、远程过程以及服务器端的stub过程构成。分派器明白远程过程号是怎样与服务器一端的stub过程相对应的,它利用这种对应性将每个传入远程过程转发到何时的stub上。
为构建应用程序的分布式,程序员必须将一个或者多个过程转移到远程机器中。在这样做时,只要客户端的stub过程具有同最初被调用的过程一样的名字,那么,增加这个stub过程还是可以允许最初的调用和被调用过程保持不变
rpcgen
使用rpcgen生成分布式程序
很明显,实现RPC服务器所需要的多数代码是不变的,因此ONC RPC的实现包括一个工具,它自动生成实现分布式程序所需要的大多数代码。这个工具叫做rpcgen
- rpcgen读取一个规约文件作为输入,生成C的源文件作为输出。
- 规约文件包含常量、全局数据类型、全局数据以及远程过程(包括过程参数和结果类型)的声明。
- rpcgen产生的代码包含了实现客户和服务器程序所需要的大部分源代码。具体的说,rpcgen为客户端和服务器生成stub过程,它包括参数整理、发送RPC报文、把传入调用分派到正确的过程、发送应答、在参数和结果的外部表示和本地数据表示之间进行转换
- rpcgen的输出在于应用程序和程序员编写的少数文件相结合之后,就产生了完整的客户和服务器程序
rpcgen的输出和接口部分
为了维护的灵活性,并允许自动生成stub过程的大部分代码,rpcgen将每个stub过程分成了两个部分。
- 一个部分几乎对所有使用RPC的应用都是共同的,它提供基本的客户-服务器通信;
- 另一部分为应用程序提供了接口。
rpcgen由远程过程以及参数的描述出发,自动产生了stub过程的通信部分。因为rpcgen为通信stub产生了代码,它指明了客户端所要求的参数以及服务器端的调用序列。在使用rpcgen所生成的通信stub时,程序员必须接受rpcgen的调用约定。
如上图,stub的两个部分都包含两个过程。在客户端,接口过程调用通信过程。在服务器端,通信过程调用接口过程
rpcgen的输入和输出
rpcgen读取输入文件,该文件包含对远程过程的说明。它产生四个输出文件,每个文件都包含源代码。rpcgen从输入文件的名字推导出输入文件的名字。如果规约文件具有名字Q.x,那么所有输出文件名都将以Q开始。下面里除了其输出文件,并描述了内容
文件名 | 内容 |
---|---|
Q.h | 常量和类型的声明,这些常量和类型用于为客户和服务器所产生的代码中 |
Q_xdr.c | XDR过程调用,客户和服务器用于对参数的序列化 |
rdict_clnt.c | 客户端的通信stub过程 |
Q_svc.c | 服务器的通信stub过程 |
使用rpcgen构建客户和服务器
下图说明了为使用rpcgen来构建客户和服务器程序必须要编写的文件。从本质上来说,rpcgen要求程序员编写应用程序、它所要调用的过程以及客户端和服务端stub的接口部分。
当rpc运行时,它读取规约,生成C源代码,这些代码必须被编译连接,以便产生可以运行的程序。在rpcgen运行之后,要有两个单独编译和连接的步骤。一个产生可执行的客户程序,一个产生可执行的服务器
总结
RPC是使用性很广的概念,它可以帮助程序员设计客户-服务器软件。程序员可以使用RPC来帮助指明或者实现分布式程序。在使用ONCPRC时,程序员可以选用各种方式,比如从头开始构建改名、使用库、使用rpcgen的程序自动生成
RPC运行程序员构建传统的程序,然后把一些过程转移到某台远程机器中,通过这种方法将这个程序转换为分布式程序。使用stub允许最初的调用者和被调用过程保持不变。
由于大多数使用RPC的分布式程序具有一般性的体系结构,因此rpcgen可以自动生成所需的大部分但。程序员除了创建规约文件外,只需要提供一对接口过程以及与应用相关的一些过程。rpcgen生成客户和服务器程序剩下的部分,包括服务器向端口映射器注册、在客户和服务器之间提供通信以及将传入的调用分派给正确的远程过程