分享
 
 
 

Sun RPC 编程简介

王朝other·作者佚名  2006-11-24
窄屏简体版  字體: |||超大  

关键字:

RPC Socket TI-RPC TCP UDP C/S ONC

摘要:

本文简单介绍了RPC(Remote Procedure Call 远程过程调用)的原理结构、特点,

及其开放给编程人员不同层次的编程接口。并且例举实例示度绾瓮ü齊pcgen 编译工

具来快速开发RPC应用。

一、 概述

在传统的编程概念中,过程是由程序员在本地编译完成,并只能局限在本地运行的一段

代码,也即其主程序和过程之间的运行关系是本地调用关系。因此这种结构在网络日益

发展的今天已无法适应实际需求。总所周知,传统过程调用模式无法充分利用网络上其

他主机的资源(如CPU、Memory等),也无法提高代码在实体间的共享程度,使得主机资

源大量浪费。

而本文要介绍的RPC编程,正是很好地解决了传统过程所存在的一系列弊端。通过RPC我

们可以充分利用非共享内存的多处理器环境(例如通过局域汪连接得多台工作站),这样

可以简便地将你的应用分布在多台工作站上,应用程序就像运行在一个多处理器的计算机

上一样。你可以方便的实现过程代码共享,提高系统资源的利用率,也可以将以大量数值

处理的操作放在处理能力较强的系统上运行,从而减轻前端机的负担。

二、 RPC的结构原理及其调用机制

如前所述RPC其实也是种C/S的编程模式,有点类似C/S Socket 编程模式,但要比它

更高一层。当我们在建立RPC服务以后,客户端的调用参数通过底层的RPC传输通道,可以

是UDP,也可以是TCP(也即TI-RPC-无关性传输),并根据传输前所提供的目的地址及RPC

上层应用程序号转至相应的RPC Application Porgramme Server ,且此时的客户端处于等

待状态,直至收到应答或Time Out超时信号。具体的流程图如F1。当服务器端获得了请求

消息,则会根据注册RPC时告诉RPC系统的例程入口地址,执行相应的操作,并将结果返回

至客户端。

F1

当一次RPC调用结束后,相应线程发送相应的信号,客户端程序才会继续运行。

当然,一台服务主机上可以有多个远程过程提供服务,那么如何来表示一个唯一存

在的远程过程呢?一个远程过程是有三个要素来唯一确定的:程序号、版本号和过程号。

程序号是用来区别一组相关的并且具有唯一过程好的远程过程。一个程序可以有一个或几

个不同的版本,而每个版本的程序都包含一系列能被远程调用的过程,通过版本的引入,

使得不同版本下的RPC能同时提供服务。每个版本都包含有许多可供远程调用的过程,每个

过程则有其唯一标示的过程号。

三、 基于RPC的应用系统开发

通过以上对RPC原理的简介后,我们再来继续讨论如何来开发基于RPC的应用系统。

一般而言在开发RPC时,我们通常分为三个步骤:

a、 定义说明客户/服务器的通信协议。

这里所说的通信协议是指定义服务过程的名称、调用参数的数据类型和返回参数的数据

类型,还包括底层传输类型(可以是UDP或TCP),当然也可以由RPC底层函数自动选择

连接类型建立TI-RPC。最简单的协议生成的方法是采用协议编译工具,常用的有Rpcgen,

我会在后面实例中详细描述其使用方法。

b、 开发客户端程序。

c、 开发服务器端程序。

开发客户端和服务器端的程序时,RPC提供了我们不同层次的开发例程调用接口。不

同层次的接口提供了对RPC不同程度控制。一般可分为5个等级的编程接口,接下来我们

分别讨论一下各层所提供的功能函数。

1、 简单层例程

简单层是面向普通RPC应用,为了快速开发RPC应用服务而设计的,他提供

了如下功能函数。

函数名 功能描述

Rpc_reg( ) 在一特定类型的传输层上注册某个过程,来作为提供服务的RPC程序

Rpc_call( ) 远程调用在指定主机上指定的过程

Rpc_Broadcast( ) 向指定类型的所有传输端口上广播一个远程过程调用请求

2、 高层例程

在这一层,程序需要在发出调用请求前先创建一个客户端句柄,或是在侦听请

求前先建立一个服务器端句柄。程序在该层可以自由的将自己的应用绑在所有的

传输端口上,它提供了如下功能函数。

函数名 功能描述

Clnt_create( ) 程序通过这个功能调用,告诉底层RPC服务器的位置及其传输类型

Clnt_create_timed( ) 定义每次尝试连接的超时最大时间

Svc_create( ) 在指定类型的传输端口上建立服务器句柄,告诉底层RPC事件过程的相应入口地址

Clnt_call() 向服务器端发出一个RPC调用请求

3、 中间层例程

中间层向程序提供更为详细的RPC控制接口,而这一层的代码变得更为复杂,

但运行也更为有效,它提供了如下功能函数。

函数名 功能描述

Clnt_tp_create( ) 在指定的传输端口上建立客户端句柄

Clnt_tp_create_timed( ) 定义最大传输时延

Svc_tp_creaet( ) 在指定的传输端口上建立服务句柄

Clnt_call( ) 向服务器端发出RPC调用请求

4、 专家层例程

这层提供了更多的一系列与传输相关的功能调用,它提供了如下功能函数。

函数名 功能描述

Clnt_tli_create( ) 在指定的传输端口上建立客户端句柄

Svc_tli_create( ) 在指定的传输端口上建立服务句柄

Rpcb_set( ) 通过调用rpcbind将RPC服务和网络地址做映射

Rpcb_unset( ) 删除rpcb_set( ) 所建的映射关系

Rpcb_getaddr( ) 调用rpcbind来犯会指定RPC服务所对应的传输地址

Svc_reg( ) 将指定的程序和版本号与相应的时间例程建起关联

Svc_ureg( ) 删除有svc_reg( ) 所建的关联

Clnt_call( ) 客户端向指定的服务器端发起RPC请求

5、 底层例程

该层提供了所有对传输选项进行控制的调用接口,它提供了如下功能函数。

函数名 功能描述

Clnt_dg_create( ) 采用无连接方式向远程过程在客户端建立客户句柄

Svc_dg_create( ) 采用无连接方式建立服务句柄

Clnt_vc_create( ) 采用面向连接的方式建立客户句柄

Svc_vc_create( ) 采用面向连接的方式建立RPC服务句柄

Clnt_call( ) 客户端向服务器端发送调用请求

四、 实例介绍

以下我将通过实例向读者介绍通过简单层RPC的实现方法。通常在此过程中我们

将使用RPC协议编译工具-Rpcgen。Rpcgen 工具用来生成远程程序接口模块,它将以RPC

语言书写的源代码进行编译,Rpc 语言在结构和语法上同C语言相似。由Rpcgen 编译生

成的C源程序可以直接用C编译器进行编译,因此整个编译工作将分为两个部分。Rpcgen

的源程序以.x结尾,通过其编译将生成如下文件:

a) 一个头文件(.h)包括服务器和客户端程序变量、常量、类型等说明。

b) 一系列的XDR例程,它可以对头文件中定义的数据类型进行处理。

c) 一个Server 端的标准程序框架。

d) 一个Client 端的标准程序框架。

当然,这些输出可以是选择性的,Rpcgen 的编译选项说明如下:

选项 功能

'-' a 生成所有的模板文件

'-' Sc 生成客户端的模板文件

'-' Ss 生成服务器端的模板文件

'-' Sm 生成Makefile 文件

(详见Solaris Rpcgen Manaul)

Rpcgen 源程序 time.x:

/* time.x: Remote time printing protocol */

program TIMEPROG {

version PRINTIMEVERS {

string PRINTIME(string) = 1;

} = 1;

} = 0x20000001;

time_proc.c源程序:

/* time_proc.c: implementation of the remote procedure "printime" */

#include <stdio.h>

#include <rpc/rpc.h> /* always needed */

#include "time.h" /* time.h will be generated by rpcgen */

#include <time.h>

/* Remote version of "printime" */

char ** printime_1(char **msg,struct svc_req *req)

{

static char * result; /* must be static! */

static char tmp_char[100];

time_t rawtime;

FILE *f;

f = fopen("/tmp/rpc_result", "a+");

if (f == (FILE *)NULL) {

strcpy(tmp_char,"Error");

result = tmp_char;;

return (&result);

}

fprintf(f, "%s\n", *msg); //used for debugging

fclose(f);

time(&rawtime);

sprintf(tmp_char,"Current time is :%s",ctime(&rawtime));

result =tmp_char;

return (&result);

}

rtime.c源代码

/*

* rtime.c: remote version

* of "printime.c"

*/

#include <stdio.h>

#include "time.h" /* time.h generated by rpcgen */

main(int argc, char **argv)

{

CLIENT *clnt;

char *result;

char *server;

char *message;

if (argc != 3) {

fprintf(stderr, "usage: %s host message\n", argv[0]);

exit(1);

}

server = argv[1];

message = argv[2];

/*

* Create client "handle" used for

* calling TIMEPROG on the server

* designated on the command line.

*/

clnt = clnt_create(server, TIMEPROG, PRINTIMEVERS, "visible");

if (clnt == (CLIENT *)NULL) {

/*

* Couldn't establish connection

* with server.

* Print error message and die.

*/

clnt_pcreateerror(server);

exit(1);

}

/*

* Call the remote procedure

* "printime" on the server

*/

result =*printime_1(&message,clnt);

if (result== (char *)NULL) {

/*

* An error occurred while calling

* the server.

* Print error message and die.

*/

clnt_perror(clnt, server);

exit(1);

}

/* Okay, we successfully called

* the remote procedure.

*/

if (strcmp(result,"Error") == 0) {

/*

* Server was unable to print

* the time.

* Print error message and die.

*/

fprintf(stderr, "%s: could not get the time\n",argv[0]);

exit(1);

}

printf("From the Time Server ...%s\n",result);

clnt_destroy( clnt );

exit(0);

}

有了以上的三段代码后,就可用rpcgen 编译工具进行RPC协议编译,命令如下:

$rpcgen time.x

rpcgen 会自动生成time.h、time_svc.c、time_clnt.c

再用系统提供的gcc进行C的编译,命令如下:

$gcc rtime.c time_clnt.c -o rtime -lnsl //客户端编译

$gcc time_proc.c time_svc.c -o time_server -lnsl //服务器端编译

编译成功后即可在Server端运行time_server,立即将该服务绑定在rpc服务端口上提供

服务。在客户端运行./rdate hostname msg (msg 是一字符串,笔者用来测试时建立的),

立即会返回hostname 端的时间。

由于,在Sun Solaris 中无法获取远端Server 上时钟信息的功能(不改变本

地Server时钟),笔者曾将此程序应用于计费服务器同时钟服务器同步监测的网管

系统中,运行稳定,获得了较好的效果。应该说RPC的应用是十分广泛的,特别是

在分布式计算领域中尤为显得重要。当然,笔者也是刚接触RPC,还有很多地方了

解的不够深刻,望广大读者多指教。

参考文献:

《SUN Solaris8 ONC+ Dev》

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有