📄 rfc1050.txt
字号:
组织:中国互动出版网(http://www.china-pub.com/)
RFC文档中文翻译计划(http://www.china-pub.com/compters/emook/aboutemook.htm)
E-mail:ouyang@china-pub.com
译者:马东辉(eaststone ma_donghui@263.net )
译文发布时间:2001-3-28
版权:本翻译文档可以用于非商业用途自由转载,但必须保留本文档的翻译及组织信息。
Network Working Group Sun Microsystems, Inc.
Request for Comments: 1050 April 1988
远程过程调用协议规范
(RFC1050---Remote Procedure Call Protocol Specification)
摘要
远程过程调用(Remote Procedure Call)可以使程序调用远方节点上的过程象调用本地过程一样方便。本文就是远程过程调用协议规范的中文版。
目录
1.简介 1
2.术语 2
3.RPC的模型 2
4.传输和语义 2
5. 绑定与集合独立性 3
6.认证 4
7.RPC协议的要求 4
8. RPC消息协议 7
9.认证协议 10
10.记录标记的标准 16
11.RPC语言 16
附录A:端口映射器程序协议 18
1.简介
此文档详细说明了一个使用在实现Sun公司的远程过程调用(RPC)包中的消息协议。此消息协议是由外部数据描述(XDR)语言[9]来定义的。这篇文档假定读者对XDR非常熟悉,它并不试图去证明使用RPC的好处。这里推荐由Birrell and Nelson [1]所写的文章,作为了解RPC的背景。
2.术语
此文档讨论了服务器,服务,程序,过程,客户和版本这些术语。服务器就是实现网络服务的软件。网络服务是一个或多个远程程序的集合。一个远程程序实现了一个或多个远程过程;这些过程的参数和结果已经存档在特定的程序协议规范中(见附录A中的例子)。网络客户是向服务发出远程过程调用的软件。一个服务器可能支持不止一种版本的远程程序,这样以便于与改变的协议兼容。
例如,一个网络文件服务可能由两个程序组成。一个程序处理诸如文件系统访问控制和锁定这样的高层应用。另一个程序处理低层的文件I/O,拥有象“read”和“write”这样的过程。网络文件服务的客户机根据自己用户的需要将会调用服务中与这两个程序关联的过程。
3.RPC的模型
远程过程调用模型与本地过程调用模型非常相似。在本地过程调用中,调用者把要传给过程的参数放在明确定义好的位置上(例如一个结果记录)。然后调用者将把控制转交到被调用的过程中,最后得到返回的控制。在返回点上,被调用的过程的结果从明确定义好的位置上取出,调用者继续执行。
远程过程调用也是相似的,通过两个进程逻辑地运行在一起构成一条控制主线。一个是调用者进程,另一个是服务器进程。也就是说,调用者进程发送给服务器进程一条调用消息,并等待(阻塞)直到收到响应的消息。调用消息包含被调用的过程的参数等。响应消息包含着被调用过程的结果等。一旦收到响应消息,被调用过程的结果就会被取出,调用者将恢复执行。
在服务器一侧,一个进程处于休眠状态来等待调用消息的到达。当一条调用消息到达后,服务器进程从消息中取出被调用过程的参数,计算出结果,发送响应消息,然后等待下一条调用消息。
注意:这种模式中,在任一个给定的时间上,两个进程中只有一个是激活的。但是,这种模式只是作为一个例子。RPC协议在并发模型的实现上不作限制,也可能存在着其它的实现并发模型的方法。例如,一种实现可能选择RPC调用是异步进行的,这样客户机就可以在等待服务器的响应中,做其它有用的工作。另一种可能性是使服务器创建一个新的任务来处理输入的请求,这样服务器就可以自由地接收其它的请求。
4.传输和语义
RPC协议不依赖于传输协议。也就是说,RPC不关心消息是怎样从一个进程传递到另一个进程中去的。这个协议仅仅处理协议的规范和消息的解释。
还有必要指出RPC并不去试图实现任何一种可靠性,所以应用程序必须考虑在RPC下层的传输层协议。如果应用程序知道自己运行在象TCP/IP[6]这样的可靠传输层的上层的时候,它就知道保证可靠性的大部分工作已经做好了。在另一方面,如果应用程序运行在象UDP/IP[7]这样的不可靠传输层的上层,那么它必须实现自己的重传和超时策略,而这些服务RPC层是不提供的。
因为独立于传输层,RPC协议并不把特殊的语义附加到远程过程上。可以从下面的传输层推断出来(但是应该有明确的定义)。例如,考虑RPC运行在不可靠传输层UDP/IP的上层。如果应用程序在很短的超时后重传RPC消息,当没有接收到响应的时候,它能够判断的唯一的事情就是过程没有执行或者执行了一次以上。当收到响应的时候,它可以推断出过程至少执行了一次。
服务器可能希望记住以前准许的从客户端发来的请求。为了在某种程度上确保至多只执行一次的语义,服务器不再重新批准这些请求。服务器通过利用打包在RPC请求中的事务ID来实现这个功能。事务的主要用处就是客户端的RPC层用它来匹配对请求的响应。但是,客户应用程序当重传一个请求的时候可以选择再使用它以前的事务ID。服务器应用程序在知道了这个事实后,可以选择在准许了一个请求后记住这个事务ID,为了获得在某种程度上至多只执行一次的语义,服务器对于具有相同ID的请求不再重新批准。除了可以进行检验相等的操作之外,不允许服务器使用其它的方法来检查这个ID。
另一方面,如果使用了一个象TCP/IP这样的可靠传输,应用程序能够从一条响应消息推断出过程已经正确地执行了一次。但是,如果它没有接收到响应消息,则不能假设远程过程没有执行。注意:即使使用了象TCP这样的面向连接的协议,应用程序仍然需要超时和重新连接的功能来处理服务器崩溃的情况。
除了数据报或者面向连接的协议之外,还存在其它的传输层协议的可能性。例如,一种象VMTP[2]这样的请求响应协议对RPC来说也许是最自然的传输层协议。
注意:在Sun中,RPC当前实现在TCP/IP以及UDP/IP的上层。
5. 绑定与集合独立性
绑定一个客户端到一个服务上的行为并不是远程过程调用规范的一部分。这个重要且必要的功能留给了一些上层的软件(这个软件可能本身就使用RPC,见附录A)
执行者应该把RPC协议看作是网络上的跳转到子程序指令("JSR");装载程序(绑定者)使JSR可用,装载程序本身使用JSR来完成它自己的任务。同样,网络使RPC可用,使用RPC来完成它的任务。
6.认证
RPC协议提供了一些必要的字段使客户能向服务标识它自己,反过来服务也要用一些字段来向客户标识自己。安全和访问控制机制建立在消息认证之上。一些不同的认证协议能够得到支持。在RPC报头中有一个字段用来指出使用哪一种认证协议。关于更详细的认证协议的信息在第九节“认证协议”中讨论。
7.RPC协议的要求
RPC协议必须要能提供以下的功能:
(1)一个调用过程的唯一规范
(2)匹配响应消息和请求消息的规则
(3)服务鉴别调用者和调用者鉴别服务的规则
除了以上的要求,还需要能检测出以下由于协议,实现,用户和网络管理中所产生的错误:
(1)RPC协议不匹配
(2)远程程序协议版本不匹配
(3)协议错误(诸如错误指定了过程参数)
(4)远程认证失败的原因
(5)不能调用想要的过程的其它原因
7.1 RPC程序和过程
RPC调用消息有三个无符号的字段:远程程序号,远程程序版本号和远程过程号。这三个字段唯一地标识了被调用的过程。程序号由一些主要的权威来管理(就象Sun公司)。一旦执行者有了一个程序号,他就可以执行他的远程程序;第一次执行很可能有一个版本号1。因为大多数新的协议都发展成更好,更稳定,更成熟的协议,所以调用消息中的版本字段标识了调用者使用了协议的哪一个版本。版本号使得通过相同的服务器进程运行旧协议和新协议成为可能。
过程号标识着被调用的过程。这些号码已经归档在特定的程序的协议规范中。例如,文件服务协议规范可能把它的过程号5定义为“read”,过程号12定义为“write”。
就像远程程序协议在一些版本上可能有一些变化一样。实际的RPC消息协议也可能有所改变。因此,调用消息也有它自己的RPC版本号。对于在这里描述的RPC来说,这个版本号总是等于2。
请求消息的响应消息具有足够的信息来区分下面的错误情况:
(1) RPC的远程实现应该使用协议的第二版,RPC协议支持的最低和最高版本号
将返回。
(2)远程程序在远程系统中不可用。
(3)远程程序不支持请求的版本号。远程程序支持的最低和最高版本号将返回。
(4)请求的过程号不存在。(这总是因为调用者一方的协议或者程序出错)
(5)传给远程过程的参数在服务器看来是无用的(这实际上是由客户端和服务器之间的协议没有达成一致造成的)。
7.2 认证
服务器对调用者的认证和调用者对服务器的认证的规则是RPC协议的一部分。调用消息有两个认证字段,证书和校验符响应消息有一个认证字段,即响应校验符。RPC协议规范把这三个字段都定义成不透明的类型。
enum auth_flavor {
AUTH_NULL = 0,
AUTH_UNIX = 1,
AUTH_SHORT = 2,
AUTH_DES = 3
/* 更多的定义 */
};
struct opaque_auth {
auth_flavor flavor;
opaque body<400>;
};
用简单的英语表示,任何一个"opaque_auth"结构就是由一个"auth_flavor"枚举类型后跟一些对RPC协议实现来说是不透明的字节组成的。
在认证字段中包含的数据的语义和解释是个别指定的,独立于认证协议规范。(第九节定义了不同的认证协议)
如果认证参数被拒绝,响应消息将包含说明为什么会被拒绝的信息。
7.3 程序号分配
程序号根据下表以十六进制20000000(十进制536870912)为一组来进行分发。
0 - 1fffffff 由Sun公司定义
20000000 - 3fffffff . 由Sun公司定义
40000000 - 5fffffff 暂时的
60000000 - 7fffffff 保留
80000000 - 9fffffff 保留
a0000000 - bfffffff 保留
c0000000 - dfffffff 保留
e0000000 - ffffffff 保留
第一组是属于升阳微系统公司(Sun公司)管理的号码范围。在所有场所都应该是一致的。第二组号码范围对应用程序来说对特定场所是特有的。这个范围主要是用来调试新程序的。当在一个场所中开发的一个应用程序要引起公众的注意,这个应用程序就应该在第一组号码范围中分配一个号码。第三组号码范围对应用程序来讲是动态地产生程序号。最后的那些号码范围组是为将来使用保留的,目前还没有使用。
7.4 RPC协议的其它使用
使用RPC协议的主要目的就是为了调用远程的过程。也就是说,每一个调用消息都与一个响应消息匹配。但是,这个协议本身是一个消息传送协议,其它协议(非RPC协议)也可以通过这个协议来实现。Sun当前正在为下面两种非RPC协议使用 RPC消息协议,这两种协议是批处理(或者管道)和广播RPC,下面将讨论,但是不详细说明。
7.4.1 批处理
批处理允许客户发送一个任意大的调用消息序列给服务器;它典型地使用可靠字节流协议(象TCP/IP)来作为它的传输层。在批处理的时候,客户从来不等待服务器的响应,服务器也不发送对批处理请求的响应。一个批处理调用序列总是由合法的RPC终止,这是为了刷新管道(以肯定确认)。
7.4.2广播RPC
在基于广播RPC的协议中,客户向网络中发送一个广播数据包,然后等待响应。广播RPC使用不可靠的数据报协议(象UDP/IP)作为它的传输层。支持广播协议的服务器只有在请求被成功执行后才进行响应。在出错的时候服务器将保持沉默。广播RPC使用端口映射器RPC服务来获得它的语义。(要获得更多的信息请参见附录A)
8. RPC消息协议
这一节用XDR数据定义语言来定义RPC消息协议。这些消息是用一种严谨的风格来定义的。.
enum msg_type {
CALL = 0,
REPLY = 1
};
/*
*调用消息的响应可以呈现出两种形式;
*消息要么被接受要么被拒绝
*/
enum reply_stat {
MSG_ACCEPTED = 0,
MSG_DENIED = 1
};
/*
*如果一条调用消息被接受,下面是试图调用远程过程的状态。
*/
enum accept_stat {
SUCCESS = 0, /* RPC执行成功 */
PROG_UNAVAIL = 1, /* 远程没有输出程序 */
PROG_MISMATCH = 2, /* 远程不支持版本号 */
PROC_UNAVAIL = 3, /* 程序不支持过程 */
GARBAGE_ARGS = 4 /* 过程不能解释参数 */
};
/*
* 调用消息被拒绝的原因
*/
enum reject_stat {
RPC_MISMATCH = 0, /* RPC版本号不等于2 */
AUTH_ERROR = 1 /* 远程不能认证调用者 */
};
/*
* 认证失败的原因
*/
enum auth_stat {
AUTH_BADCRED = 1, /* 错误的证书 (封装被打破) */
AUTH_REJECTEDCRED = 2, /* 客户必须开始新会话 */
AUTH_BADVERF = 3, /* 错误的校验符 (封装被打破) */
AUTH_REJECTEDVERF = 4, /* 校验符过期或者重放 */
AUTH_TOOWEAK = 5 /* 因为安全原因拒绝 */
};
/*
* RPC消息
*所有消息以一个事务标识符xid开始,接下来是有判别的两个分支的联合。
*这个联合的判别式是msg_type等于两类消息的一种。
*响应消息的xid总是匹配开始调用消息的xid。
*客户端使用这个字段把收到的响应消息与调用消息配备,
*服务器端使用这个字段来检测重传。
*服务器端不能把这个id看作为任何一种类型的序列号。
*/
struct rpc_msg {
unsigned int xid;
union switch (msg_type mtype) {
case CALL:
call_body cbody;
case REPLY:
reply_body rbody;
} body;
};
/*
* RPC请求调用的实体:
*在RPC协议规范的版本2中,rpcvers字段必须等于2。
*字段prog, vers,和proc确定了远程程序,以及程序的版本号
*和在远程程序中被调用的过程。在后面是两个认证参数
*cred(认证证书)和verf(认证校验符)。认证参数的下面是远程过程的参数,
*这些参数是由具体的程序协议来指定的。
*/
struct call_body {
unsigned int rpcvers; /* 必须等于2 */
unsigned int prog;
unsigned int vers;
unsigned int proc;
opaque_auth cred;
opaque_auth verf;
/* 过程的特定参数从这里开始 */
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -