RPC编程指导(rpc编程实例)

使用RPC编程

远程过程调用 Remote Procedure Call

-------------------------------------

通过stub函数,远程的执行过程可以被本地调用

客户端拥有相同的函数接口

Stub 函数的产生

- 使用独立的预编译器rpcgen来使编程语言支持

- 结构定义语言

接口定义语言 Interface Definition Language

type definitions

program identifier{

version version_id{

procedure list

}=value;

...

}=value;

program PROG{

version PROG1{

void PROC_A(int) = 1;

}=1;

}=0x3a3afeeb;

数据类型

struct intpair {int a, b};

struct intpair {int a; int b;};

typedef struct intpair intpair;

数据类型

enum state {BUSY=1, IDLE=2, TRANSIT=3};

union identifier switch (declaration) {

case_list

}

union time_s switch (int status) {

case 0: char timeval [MAXBUF];

case 1: void;

case 2: int reason;

}


数据类型

- 和C相似

- typedef long counter;

- 和C相似,但具有可变长度

long x_vals<50>代表一个最长为50的数组

- 和C相似。在指针指向的数据前有个布尔值,如果指针为null,则布尔值 为FALSE

数据类型

类似声明一个长度可变的数组

string name<50> 一个最长50的字符串 string name<> 一个任意长度的字符串

可以拥有TRUE和FALSE两种值

一组按位顺序存储的没有类型的数据,长度可变。

opaque extra_bytes[512];

稍后声明将会转换为C形式:

struct {

uint more_len; /* 数组长度 */

char *more_val; /* 数据使用的空间 */

};

使用SUN RPC创建例程

- 小写

- 由自定义名字,版本号和"svc"三部分组成,例如BLIP, blip_1_svc

- 可以使用使用结构体传递多个值

- 在较新的版本中rpcgen对这个限制放宽了,但仍是作为默认情况


一个简单的RPC程序

- bin_date返回系统时间,即从1970年第一秒开始的秒数

- str_date把秒数作为输入,返回一个格式化的字符串

- 将bin_date和str_date移动到服务器,通过RPC来调用她们。

Stand-alone程序

#include <stdio.h>

long bin_date(void);

char *str_date(long bintime);

main(int argc, char **argv) {

long lresult; /* 从bin_date()返回的值 */

char *sresult; /* 从str_date()返回的值 */

if (argc != 1) {

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

exit(1);

}

/* 调用bin_date()过程 */

lresult = bin_date();

printf("time is %ld/n", lresult);

/* 格式化输出结果 */

sresult = str_date(lresult);

printf("date is %s", sresult);

exit(0);

}

Stand-alone程序:函数

/* bin_date 以二进制的形式返回系统时间 */

long bin_date(void) {

long timeval;

long time(); /* 返回时间 */

timeval = time((long *)0);

return timeval;

}

/* str_date 转换时间从二进制到格式化字符串 */

char *str_date(long bintime) {

char *ptr;

char *ctime();

ptr = ctime(&bintime);

return ptr;

}

定义远程接口(IDL)

- bin_date()没有参数,返回一个long型结果

- str_date()接受一个long型作为输入,然后返回字符串

program DATE_PROG {

version DATE_VERS {

long BIN_DATE(void) = 1;

string STR_DATE(long) = 2

} = 1;

} = 0x31423456;


产生服务器函数:rpcgen的模板

rpcgen -C -Ss date.x >server.c

#include "date.h"

long *

bin_date_1_svc(void *argp, struct svc_req *rqstp)

{

static long result;

/* insert server code here */

return &result;

}

char **

str_date_1_svc(long *argp, struct svc_req *rqstp)

{

static char *result;

/* insert server code here */

return &result;

}

产生服务器函数:插入代码

long *

bin_date_1_svc(void *argp, struct svc_req *rqstp)

{

static long result;

long time();

result = time((long *)0);

return &result;

}

char **

str_date_1_svc(long *bintime, struct svc_req *rqstp)

{

static char *result;

char *ctime();

result = ctime(bintime);

return &result;

}

产生客户端函数:获得服务器名字

- 使用getopt库函数从命令行接收的-h hostname参数。

extern char *optarg;

extern int optind;

char *server = "localhost"; /* default */

int err = 0;

while ((c = getopt(argc, argv, "h:")) != -1)

switch (c) {

case 'h':

server = optarg;

break;

case '?':

err = 1;

break;

}

/* exit if error or extra arguments */

if (err || (optind < argc)) {

fprintf(stderr, "usage: %s [-h hostname]/n", argv[0]);

exit(1);

}

产生客户端函数:添加头文件和创建客户端句柄

#include <rpc/rpc.h>

#include "date.h"

CLIENT *c1;

c1 = clnt_create(server, DATE_PROG, DATE_VERS, "netpath");

产生客户端函数:修改远程函数的调用

- 给函数添加版本号

- 添加一个客户端的句柄作为参数(由clnt_create返回)

- 经常传递单个参数(如果没有的话就传递NULL)

bin_date_1(NULL, c1);

str_date_1(&value, c1);

产生客户端函数:检查RPC错误

long *lresult;

if ((lresult = bin_date_1(NULL, c1)) == NULL){

clnt_perror(c1, server);

exit(1);

}

产生客户端函数:检查RPC错误(2)

char **sresult;

if((sresult = str_date_1(lresult, c1)) == NULL)

{

clnt_perror(cl, server);

exit(1);

}

printf("date is %s", *sresult);

编译-连接-运行

生成stubs

rpcgen -C date.x

编译连接客户端和客户端stub

cc -o client client.c date_clnt.c -lnsl

编译连接服务器和服务器stub

cc -o server -DRPC_SVC_FG server.c date_svc.c -lnsl

$ ./server

$ ./client -h remus

time on localhost is 970457832

date is Sun Oct 1 23:37:12 2000


上文来自:http://blog.csdn.net/beff2047/article/details/4028568