ONC远程过程调用协议

ONC RPC的Java开发包为 Remote Tea http://remotetea.sourceforge.net/ 包含三部分内容, 1. jrpcgen 根据.x定义生成java源码 2. jportmap 是一个守护进程,开启监听端口,收发数据。 3. oncrpc 主要的实现包。 实现RPC功能的步聚: 1. 根据.x生成java源码. Java –jar jrpcgen.jar –p packageName example.x 2. 服务端实现, 实现一个继承ServerStub的类,对里面实现的抽象实现。 3. 客户端的实现 demoClient client = null; try { client = new demoClient(InetAddress.getByName("127.0.0.1"), OncRpcProtocols.ONCRPC_TCP); } catch ( Exception e ) { System.out.println("demoClientExample: oops when creating RPC client:"); e.printStackTrace(System.out); } client.getClient().setTimeout(300*1000); System.out.print("About to ping: "); try { client.NULL_1();//调用接口的方法 System.out.println("ok"); } catch ( Exception e ) { e.printStackTrace(System.out); return; } 4. 服务端启动方法, 1. 启动portmap jportmap pmap = new jportmap(); pmap.run(pmap.transports); 2. 启动服务 demoServer server = new demoServer(); server.run(); 3. 关闭RPC服务, pmap.close(pmap.transports); RFC1831-1833 ONC远程过程调用协议 摘要 本文描述了ONC远程过程调用协议。ONC为“开放网络计算机”。 1. 简介 本文描述了ONC远程过程调用使用的报文协议。报文协议用XDR语言描述。本文假定读者熟悉XDR语言。 2. 术语 每个远程过程调用有两方面:活跃客户端发出请求,服务器端给出回答。一个网络服务是一个或多个远程程序的集合。远程程序实现一个或多个远程过程;这些过程及其参数、结果由特定的程序协议记录。服务器可能支持多个版本的远程程序以与变化的协议兼容。 例如,网络文件服务可能由两个程序组成。一个程序用于处理高级应用,如文件系统读写控制和锁。另一个程序处理低级文件输入和输出。网络文件服务的客户端将调用这两个程序。 客户端和服务器端只应用与特定的事务中;硬件实体和软件实体在不同时刻可以扮演不同角色。如,一个远程服务程序也可以是网络文件服务的客户端。 3. RPC模型 ONC RPC协 议基于远程过程调用模型,类似于本地过程调用模型。在本地过程调用模型中,调用者把过程的参数放在特定的位置。接着,它把控制传给过程,过程的结果可以从 特定的位置得到,调用者继续执行。远程过程调用模型也是类似的。控制在两个进程中传递:调用者进程和服务器进程。调用者进程首先向服务器进程发出请求报 文,然后等待回答。调用报文包括过程的参数,回答报文包括过程的结果。一旦接收到应答报文,就可获取过程的结果,调用者继续执行。 在服务器端,一个进程睡眠等待调用报文的到来。当有调用报文时,服务器进程提取过程的参数,计算出结果,发送应答报文,接着等待下一条报文。 在这种模型中,在任一时刻最多只有一个进程时活跃的。但这种模型只是一个例子。ONC RPC协议对于并发模型没有限制。例如,可以有填补的RPC调用,这样,客户端在等待服务器回答时可以更有效的工作。另一种作法是在服务器端开辟一个新的任务处理到来的调用,这样服务器还可以处理其它的请求。 远程过程调用和本地过程调用有以下不同: 1. 错误处理:远程过程调用中必须处理远程服务器和网络错误。 2. 全局变量:由于服务器端不能读写客户端的地址空间,隐含参数不能作为全局变量传递。 3. 效率:远程过程比本地过程慢。 4. 认证:由于远程过程调用可以在不安全的网络上传递,认证就是必须的。认证防止一个实体被冒充成另一个实体。 结论:尽管有工具可以自动为特定服务产生客户端和服务器端的库文件,协议仍需仔细设计。 4. 传输和语义 RPC协议可以在不同传输协议上实现。RPC不限制报文是如何从一个进程传递到另一个进程,但对报文规范和解释有限制。应用程序可能希望得到传输层的信息。如,传输协议可能对RPC报文的大小有限制,也可能是面向流的,如TCP,对 报文的大小没有限制。客户端和服务器端必须在协议的选择上取得一致。 必须指出RPC没有实现任何的可靠性。应用程序必须重视RPC下的传输协议。如果RPC运行在可靠传输的基础上,如TCP,大部分工作就已完成。如果运行在不可靠协议的基础上,如UDP,它就必须自己实现RPC中未支持的超时,重传,重复检测策略。 由于传输的独立性,RPC协议没有在日常过程中附加特定的语义。语义可以从下层的传输协议中得到。例如,RPC运行在不可靠传输协议上,如UDP。如果应用程序超时后重传RPC调用报文,但没有得到回答,它就不能推断出程序执行次数的信息。当它收到应答后,就可推断出程序至少被执行了一次。 服务器可能希望记住先前客户端的请求,以保证最多执行一次的语义。服务器可以通过在每个RPC报文中加上一个事务ID域来实现。事务ID域主要用于客户端实体对调用应答的匹配上。客户端应用还可以在重传一个调用时使用相同的事务ID。服务器可以在执行完一个调用后记录这个ID,然后不再执行相同ID的调用,以实现最多执行一次的语义。除非检测是否相同,服务器不能使用这个ID。 另一方面,如果使用可靠传输,如TCP,应用可以从应答报文中推断程序只执行了一次,但如果它没有收到应答报文,它不能推出远程过程没有被执行。注意即使使用了面向连接的协议,如TCP,应用仍需超时和重连以处理服务器崩溃。除了数据报和面向连接的协议,还有其它的传输协议。如,请求-应答协议如VMTP也是可以的。ONC RPC使用TCP和UDP传输协议。 5. 绑定和会晤的独立性 客户端和服务的绑定,传输参数不是RPC协议的一部分。这个重要而必须的功能由上层软件实现。开发者可能认为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调用报文有三个无符号整数域:远程程序序号、远程程序版本号、远程过程序号,它们唯一指出被调用的过程。程序序号由中心权威管理。一旦开发者有了程序序号,就可以实现远程程序;最初版本号通常为1。调用报文的版本域指出调用者使用哪个版本的协议。版本号使在同一服务器进程中同时支持新旧协议成为可能。过程序号指出被调用的过程。这些序号在程序协议规范中记录。例如,文件服务协议规范记录序号为5的过程使“读”,序号为12的过程是“写”。远程程序协议可能有几个版本,RPC报文协议也可能改变。因此,调用报文同样包括RPC版本号。应答报文包含了足够的信息来识别以下错误: 1. RPC 的远程实现不支持版本2的协议。支持的最高、最低版本号被返回。 2. 远程系统的远程程序不可用。 3. 远程程序不支持所要求的版本号。最高和最低远程程序版本号被返回。 4. 请求的过程序号不存在。(这通常是客户端协议或程序错误) 5. 远程过程的参数不可用。(这通常是客户和服务器的协议不匹配) 7.2 认证 调用者和服务的互相认证被提供为RPC协议的一部分。调用报文包含两个认证域,凭证和确认。应答报文包含一个认证域,应答确认。RPC协议规范定义这三个域为以下不透明类型(使用XDR语言) enum auth_flavor { AUTH_NONE = 0, AUTH_SYS = 1, AUTH_SHORT = 2 /*还可有更多*/ };   struct opaque_auth { auth_flavor flavor; opaque body<400>; };   换而言之,任何“opaque_auth”结构是一个对于RPC不透明(不可解释)的400字节的枚举类型“auth_flavor”。认证域数据的解释和语义由独立认证协议所规范。如果认证参数被拒绝,应答报文包含拒绝的原因。 7.3 程序序号的指定 程序序号由16进制20000000(10进制536870912)指定,如下所示: 0 - 1fffffff defined by rpc@sun.com 20000000 - 3fffffff defined by user 40000000 - 5fffffff transient 60000000 - 7fffffff reserved 80000000 - 9fffffff reserved a0000000 - bfffffff reserved c0000000 - dfffffff reserved e0000000 - ffffffff reserved 第一组是由rpc@sun.com管理的序号范围,在所有站点都必须相同。第二组是特定于站点的应用的范围。这组主要被用于跟踪新程序。当一个站点开发出一个通用应用,这个应用应在第一组中指定一个序号。开发者可以向rpc@sun.com发邮件来申请RPC程序序号。第三组应用动态产生程序序号的应用。最后一组被将来的应用所保留,不能被使用。 7.4 RPC协议的其它应用 用于远程过程调用。通常,每个调用报文都与一个应答报文匹配。 7.4.1 批处理 当客户端希望向服务器端发送大量调用报文时非常有用。批处理通常使用可靠字节流协议传输(如TCP)。批处理中,客户端不等待服务器端的回答,服务器也不向客户端发应答。批处理调用通常在合法远程过程调用操作完成后结束。 7.4.2广播远程过程调用 广播协议中,客户端向网络发送调用并等待回答。这需要基于包的协议(如UDP)作为传输协议。支持广播协议的服务器只有在成功完成调用后才发送应答,遇到错误时保持沉默。但这根据应用而不同。广播RPC的规则也适用于多点传输棗一个RPC请求被发送到多个地址。 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, /* 过程不能解析参数 */ SYSTEM_ERR = 5 /* 类似内存分配的错误 */ }; 远程过程调用被拒绝的原因: enum reject_stat { RPC_MISMATCH = 0, /* RPC version number != 2 */ AUTH_ERROR = 1 /* remote can't authenticate caller */ }; 认证失败的原因: enum auth_stat { AUTH_OK = 0, /* success */ /* * failed at remote end */ AUTH_BADCRED = 1, /* bad credential (seal broken) */ AUTH_REJECTEDCRED = 2, /* client must begin new session */ AUTH_BADVERF = 3, /* bad verifier (seal broken) */ AUTH_REJECTEDVERF = 4, /* verifier expired or replayed */ AUTH_TOOWEAK = 5, /* rejected for security reasons */ /* * failed locally */ AUTH_INVALIDRESP = 6, /* bogus response verifier */ AUTH_FAILED = 7 /* reason unknown */ };   RPC报文: 所有的报文都以事务ID,xid,开始,后跟一个联合(union)。联合的判别式是msg_type,它转换成两种报文类型之一。REPLY报文的xid总是与初始的CALL报文相匹配。注意:xid域只被客户端用于应答报文与调用报文的匹配或服务器端检测重传;服务器端不能把xid当成序号。 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; /* must be equal to two (2) */ unsigned int prog; unsigned int vers; unsigned int proc; opaque_auth cred; opaque_auth verf; /* procedure specific parameters start here */ };   PRC调用的应答体: union reply_body switch (reply_stat stat) { case MSG_ACCEPTED: accepted_reply areply; case MSG_DENIED: rejected_reply rreply; } reply;   被服务器接受的RPC调用的应答: 即使调用被接受,仍可能有错。第一个域是由服务器产生的认证确认,以便对客户端确认自身。接着是一个联合,联合的判别式是枚举accept_stat。联合的SUCCESS分支是特定于协议的。联合的PROG_UNAVAIL、 PROC_UNAVAIL、GARBAGE_ARGS和SYSTEM_ERR分支为void。PROG_MISMATCH分支指出服务器支持的远程程序最高和最低版本号。 struct accepted_reply { opaque_auth verf; union switch (accept_stat stat) { case SUCCESS: opaque results[0]; /* * procedure-specific results start here */ case PROG_MISMATCH: struct { unsigned int low; unsigned int high; } mismatch_info; default: /* * Void. Cases include PROG_UNAVAIL, PROC_UNAVAIL, * GARBAGE_ARGS, and SYSTEM_ERR. */ void; } reply_data; }; 被服务器拒绝的RPC调用的应答: 调用被拒绝有两个理由:服务器端运行一个不兼容的RPC协议(RPC_MISMATCH)或服务器拒绝调用者(AUTH_ERROR)。若RPC版本不兼容,服务器返回所支持的RPC最高和最低版本号。若为非法认证,返回失败状态。 union rejected_reply switch (reject_stat stat) { case RPC_MISMATCH: struct { unsigned int low; unsigned int high; } mismatch_info; case AUTH_ERROR: auth_stat stat; };   9. 认证协议 如前所述,认证参数是不透明的,但对RPC协议的其余部分是无限制的。本节定义两种标准的认证flavor。开发者可以发明新的认证类型,只要遵从flavor号指定规则。凭证和确认的flavor指opaque_auth结构中的flavor域。flavor号,与RPC程序序号相似,被集中控制。开发者可以向rpc2sun.com发邮件来申请新的flavor号。空认证是强制性的,它必须被实现。系统认证应尽可能地实现,许多应用使用这种认证,实现后能增强互用性。 9.1 空认证 许多调用中,并不在意客户端的身份。这时,RPC报文的凭证、确认和应答确认的flavor是“AUTH_NONE”。未定义与“AUTH_NONE”协调的透明数据。建议透明数据长度为0。 10. 记录标志标准 当RPC报文在字节流传输协议(如TCP)之上传输时,有必要把一个报文与另一个报文分隔开,以便检测和恢复协议错误。这被称为记录标志(RM)。一个RPC报文与一个RM记录相匹配。一个记录由一个或多个片段组成。一个记录片段是四字节头加0到1个字节的片段数据。字节被编码成无符号二进制数,字节顺序从高到低。数字有两个值:一个布尔型值表示这是否是记录的最后片段(若是,为1);一个31位无符号数,表示片段数据的长度。布尔型为头的高位。(注意这种记录规则不包含在SDR标准格式中) 11. RPC语言 如同有必要用正式语言描述XDR数据类型一样,也有必要用正式语言描述操作这些XDR数据类型的过程。RPC语言是XDR语言的控制扩展,以下是这种语言的精华。 11.1 RPC语言的服务例子 ping程序的例子: program PING_PROG { /* * Latest and greatest version */ version PING_VERS_PINGBACK { void PINGPROC_NULL(void) = 0; /* * Ping the client, return the round-trip time * (in microseconds). Returns -1 if the operation * timed out. */ int PINGPROC_PINGBACK(void) = 1; } = 2;   /* * Original version */ version PING_VERS_ORIG { void PINGPROC_NULL(void) = 0; } = 1; } = 1;   const PING_VERS = 2; /* latest version */ 第一个版本是带有两个过程PINGPROC_NULL和PINGPROC_PINGBACK的PING_VERS_PINGBACK。PINGPROC_NULL不要参数,不返回结果,它在计算客户端与服务器之间的往返次数时有用。约定,任何RPC协议的0号过程应有相同的语义,不需要任何类型的认证。第二个过程由客户端使用,让服务器ping客户端,返回操作所用的时间。下一版本,PING_VERS_ORIG,是协议的最初版本,不包括PINGPROC_PINGBACK过程。它与旧的客户端程序兼容。 11.2 RPC语言规范 RPC语言与XDR语言一样在RFC1014中定义,除了一下不同。 program-def: "program" identifier "{" version-def version-def * "}" "=" constant ";"   version-def: "version" identifier "{" procedure-def procedure-def * "}" "=" constant ";"   procedure-def: type-specifier identifier "(" type-specifier ("," type-specifier )* ")" "=" constant ";"   11.3 句法的注意事项 1. 有两个保留字:“ program”和“version”。 2. 一个程序定义中不能出现两次版本名或版本号。 3. 在一个版本的定义中,过程名称至多只能出现一次。 4. 程序标识与常量和类型标识在同一空间中。 5. 只有无符号常数才能被附值给程序,版本和过程。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值