转载

利用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超时信号。具体的流程图如图1。当服务器端获得了请求消息,则会根据注册RPC时告诉RPC系统的例程入口地址,执行相应的操作,并将结果返回至客 户端。当一次RPC调用结束后,相应线程发送相应的信号,客户端程序才会继续运行。

当然,一台服务主机上可以有多个远程过程提供服务,那么如何来表示一个唯一存在的远程过程呢?一个远程过程是有三个要素 来唯一确定的:程序号、版本号和过程号。程序号是用来区别一组相关的并且具有唯一过程号的远程过程。一个程序可以有一个或几个不同的版本,而每个版本的程 序都包含一系列能被远程调用的过程,通过版本的引入,使得不同版本下的RPC能同时提供服务。每个版本都包含有许多可供远程调用的过程,每个过程则有其唯 一标示的过程号。

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

通过以上对RPC原理的简介后,我们再来继续讨论如何来开发基于RPC的应用系统。一般而言在开发RPC时,我们通常分为三个步骤:

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

这里所说的通信协议是指定义服务过程的名称、调用参数的数据类型和返回参数的数据类型,还包括底层传输类型(可以是 UDP或TCP),当然也可以由RPC底层函数自动选择连接类型建立TI-RPC。最简单的协议生成的方法是采用协议编译工具,常用的有Rpcgen,我 会在后面实例中详细描述其使用方法。

b、开发客户端程序。

c、开发服务器端程序。

开发客户端和服务器端的程序时,RPC提供了我们不同层次的开发例程调用接口。不同层次的接口提供了对RPC不同程度控制。一般可分为5个等级的编程接口,接下来我们分别讨论一下各层所提供的功能函数。

1、简单层例程

简单层是面向普通RPC应用,为了快速开发RPC应用服务而设计的,他提供了如下功能函数。

利用RPC快速实现分布式系统

2、高层例程

在这一层,程序需要在发出调用请求前先创建一个客户端句柄,或是在侦听请求前先建立一个服务器端句柄。程序在该层可以自由的将自己的应用绑在所有的传输端口上,它提供了如下功能函数。

利用RPC快速实现分布式系统

3、中间层例程

中间层向程序提供更为详细的RPC控制接口,而这一层的代码变得更为复杂,但运行也更为有效,它提供了如下功能函数。

利用RPC快速实现分布式系统

4、专家层例程

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

利用RPC快速实现分布式系统

5、底层例程

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

利用RPC快速实现分布式系统

............引用文字未尽,详细请参见http://www.yuanma.org/data/2006/0918/article_1560.htm

关于“RPC语言”

RPC语言也是一种专门的编程语言,当然这里我们不需要知道太多,只需要能看懂下面这种基本结构就行了:

program TESTPROG {
version VERSION {
string TEST(string) = 1;
} = 1;
} = 87654321;

这里TESTPROG和VERSION是两个变量,用于标识一个单独的RPC接口。这被RPC服务程序,比如portmap用到,我们可以不用关心,变量名字也是随便取的。但取值要在你的系统中是唯一的。

“string TEST(string) = 1;”这一行说明有两个函数test_VERSION和test_VERSION_svc,这里由于VERSION变量为1,所以函数名为test_1和test_1_svc,这两个函数用于在服务器端和客户端实现调用,即:在客户端调用test_1函数,服务器端调用test_1_svc函数处理并返回。

函数的类型是string,RPC语言中string即C里面的一个字符串。所以上述函数有一个字符串作为参数传递,同时要返回字符串。即:char ** test_1(char **argp, CLIENT *clnt) 和 char **test_1_svc(char **argp, struct svc_req *rqstp)

同理,如果声明是这样的:

program RDICTPROG  /* name of remote program ( not used ) */
{
version RDICTVERS /* declaration of version ( see below ) */
{
int INITW ( void ) = 1; /* first procedure in this program */
int INSERTW ( string ) = 2; /* second procedure in this program */
int DELETEW ( string ) = 3; /* third procedure in this program */
int LOOKUPW ( string ) = 4; /* fourth procedure in this program */
} = 1; /* definition of the program version */
} = 0x30090949; /* remote program number ( must be unique ) */

则说明这个RPC中有四个函数可用,即客户端可以调用initw_1、insertw_1、deletew_1、lookupw_1四个函数来向服务端发送消息,服务端可以用initw_1_svc、insertw_1_svc、deletew_1_svc、lookupw_1_svc四个函数来处理请求并返回结果。

原任务

假设现在有这样一个程序,源代码如下:

/* dict.c -- main, initw, nextin, insertw, deletew, lookupw */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define MAXWORD 50 /* maximum length of a command or word */
#define DICTSIZ 100 /* maximum number of entries in dictionary. */
char dict[DICTSIZ][MAXWORD + 1]; /* storage for a dictionary of words */
int nwords = 0; /* number of words in the dictionary */
/* 函数原型 */
int nextin(char *cmd, char *word);
int initw(void);
int insertw(const char *word);
int deletew(const char *word);
int lookupw(const char *word);
/* ------------------------------------------------------------------
* main -- insert, delete, or lookup words in a dictionary as specified
* ------------------------------------------------------------------ */
int main(int argc, char *argv[])
{
char word[MAXWORD + 1]; /* space to hold word from input line */
char cmd;
int wordlen; /* length of input word */
printf("Please input:/n");
while (1) {
wordlen = nextin(&cmd, word);
if (wordlen < 0) {
exit(0);
}
switch (cmd) {
case 'I': /* 初始化 */
initw();
printf("Dictionary initialized to empty./n");
break;
case 'i': /* 插入 */
insertw(word);
printf("%s inserted./n", word);
break;
case 'd': /* 删除 */
if (deletew(word)) {
printf("%s deleted./n", word);
} else {
printf("%s not found./n", word);
}
break;
case 'l': /* 查询 */
if (lookupw(word)) {
printf("%s was found./n", word);
} else {
printf("%s was not found./n", word);
}
break;
case 'q': /* 退出 */
printf("Program quits./n");
exit(0);
break;
default: /* 非法输入 */
printf("command %c invalid./n", cmd);
break;
} /* end of switch */
} /* end of while */
return 0;
} /* end of main */

/* ------------------------------------------------------------------

* nextin -- read a command and(possibly) a word from the next input line

* ------------------------------------------------------------------ */

int nextin(char *cmd, char *word)

{

int i, ch;

ch = getc(stdin);

while (isspace(ch)) {

ch = getc(stdin);

} /* end of while */

if (ch == EOF) {

return (-1);

}

*cmd = (char) ch;

ch = getc(stdin);

while (isspace(ch)) {

ch = getc(stdin);

} /* end of while */

if (ch == EOF) {

return (-1);

}

if (ch == '/n') {

return (0);

}

i = 0;

while (!isspace(ch)) {

if (++i > MAXWORD) {

printf("error: word too long./n");

exit(1);

}

*word++ = ch;

ch = getc(stdin);

} /* end of while */

*word = '/0'; /* 原来的代码这里有问题 */

return i;

} /* end of nextin */

/* ------------------------------------------------------------------

* initw -- initialize the dictionary to contain no words at all

* ------------------------------------------------------------------ */

int initw(void)

{

nwords = 0;

return 1;

} /* end of initw */

/* ------------------------------------------------------------------

* insertw -- insert a word in the dictionary

* ------------------------------------------------------------------ */

int insertw(const char *word)

{

strcpy(dict[nwords], word);

nwords++;

return (nwords);

} /* end of insertw */

/* ------------------------------------------------------------------

* deletew -- delete a word from the dictionary

* ------------------------------------------------------------------ */

int deletew(const char *word)

{

int i;

for (i = 0; i < nwords; i++) {

if (strcmp(word, dict[i]) == 0) {

nwords--;

strcpy(dict[i], dict[nwords]);

return (1);

}

} /* end of for */

return (0);

} /* end of deletew */

/* ------------------------------------------------------------------

* lookupw -- look up a word in the dictionary

* ------------------------------------------------------------------ */

int lookupw(const char *word)

{

int i;

for (i = 0; i < nwords; i++) {

if (strcmp(word, dict[i]) == 0) {

return (1);

}

} /* end of for */

return (0);

} /* end of lookupw */

这是一个简单的字典程序,即程序运行起来以后维护着一个字典库,用户可以向里面添加词语,也可以查询或删除词语。

当然,这个程序只能在同一台主机上运行。程序整个运行过程中,只需要完成如下几个步骤:

A、接受用户输入;

B、分析用户输入决定是否进行下面的步骤:

1、初始化数据库;

2、向数据库添加词语;

3、查询或删除词语

任务分解

大家可以想到,对于一个大型系统,比如需要有很多人维护这个系统的数据。象上面这样独立的程序就不适用了,需要做成分布式系统:

即一个服务器维护着数据库,任何客户端都可以接受用户请求,客户端分析用户命令后提交给服务器去处理。

所以我们可能会把程序分成两部分:

客户端:接受用户输入,并判断用户输入内容的正确性,向服务器提交数据,等服务器返回消息

服务器端:维护数据,接受客户端命令并执行后返回结果。

所以我们把上面这个程序分解成下面两部分:

/* dict1.c -- main, nextin */
#include <stdio.h>
#include <stdlib.h>
#define MAXWORD 50 /* maximum length of a command or word */
/* ------------------------------------------------------------------
* main -- insert, delete, or lookup words in a dictionary as specified
* ------------------------------------------------------------------ */
int main(int argc, char *argv[])
{
char word[MAXWORD + 1]; /* space to hold word from input line */
char cmd;
int wordlen; /* length of input word */
printf("Please input:/n");
while (1) {
wordlen = nextin(&cmd, word);
if (wordlen < 0) {
exit(0);
}
switch (cmd) {
case 'I': /* 初始化 */
initw();
printf("Dictionary initialized to empty./n");
break;
case 'i': /* 插入 */
insertw(word);
printf("%s inserted./n", word);
break;
case 'd': /* 删除 */
if (deletew(word)) {
printf("%s deleted./n", word);
} else {
printf("%s not found./n", word);
}
break;
case 'l': /* 查询 */
if (lookupw(word)) {
printf("%s was found./n", word);
} else {
printf("%s was not found./n", word);
}
break;
case 'q': /* 退出 */
printf("Program quits./n");
exit(0);
break;
default: /* 非法输入 */
printf("command %c invalid./n", cmd);
break;
} /* end of switch */
} /* end of while */
return 0;
} /* end of main */

/* ------------------------------------------------------------------

* nextin -- read a command and(possibly) a word from the next input line

* ------------------------------------------------------------------ */

int nextin(char *cmd, char *word)

{

int i, ch;

ch = getc(stdin);

while (isspace(ch)) {

ch = getc(stdin);

} /* end of while */

if (ch == EOF) {

return (-1);

}

*cmd = (char) ch;

ch = getc(stdin);

while (isspace(ch)) {

ch = getc(stdin);

} /* end of while */

if (ch == EOF) {

return (-1);

}

if (ch == '/n') {

return (0);

}

i = 0;

while (!isspace(ch)) {

if (++i > MAXWORD) {

printf("error: word too long./n");

exit(1);

}

*word++ = ch;

ch = getc(stdin);

} /* end of while */

*word = '/0';

return i;

} /* end of nextin */

/* dict2.c -- initw, insertw, deletew, lookupw */
#include <string.h>
#define MAXWORD 50 /* maximum length of a command or word */
#define DICTSIZ 100 /* maximum number of entries in dictionary. */
char dict[DICTSIZ][MAXWORD + 1]; /* storage for a dictionary of words */
int nwords = 0; /* number of words in the dictionary */
/* ------------------------------------------------------------------
* initw -- initialize the dictionary to contain no words at all
* ------------------------------------------------------------------ */
int initw(void)
{
nwords = 0;
return 1;
} /* end of initw */

/* ------------------------------------------------------------------

* insertw -- insert a word in the dictionary

* ------------------------------------------------------------------ */

int insertw(const char *word)

{

strcpy(dict[nwords], word);

nwords++;

return (nwords);

} /* end of insertw */

/* ------------------------------------------------------------------

* deletew -- delete a word from the dictionary

* ------------------------------------------------------------------ */

int deletew(const char *word)

{

int i;

for (i = 0; i < nwords; i++) {

if (strcmp(word, dict[i]) == 0) {

nwords--;

strcpy(dict[i], dict[nwords]);

return (1);

}

} /* end of for */

return (0);

} /* end of deletew */

/* ------------------------------------------------------------------

* lookupw -- look up a word in the dictionary

* ------------------------------------------------------------------ */

int lookupw(const char *word)

{

int i;

for (i = 0; i < nwords; i++) {

if (strcmp(word, dict[i]) == 0) {

return (1);

}

} /* end of for */

return (0);

} /* end of lookupw */

这两部分代码只是在功能上实现了分离,显然实现通讯的部分还没有,下面我们利用RPC来快速实现通讯。

利用RPC实现分布式系统

首先,建立一个RPC源文件,源代码rdict.x如下:

/* rdict.x */
/* RPC declarations for dictionary program */
const MAXWORD = 10; /* maximum length of a command or word */
const DICTSIZ = 3; /* number of entries in dictionary */
struct example /* unused structure declared here to */
{
int exfield1; /* illustrate how rpcgen builds XDR */
char exfield2; /* routines to convert structures */
};
/* ------------------------------------------------------------------
* RDICTPROG -- remote program that provides insert, delete, and lookup
* ------------------------------------------------------------------ */
program RDICTPROG /* name of remote program ( not used ) */
{
version RDICTVERS /* declaration of version ( see below ) */
{
int INITW ( void ) = 1; /* first procedure in this program */
int INSERTW ( string ) = 2; /* second procedure in this program */
int DELETEW ( string ) = 3; /* third procedure in this program */
int LOOKUPW ( string ) = 4; /* fourth procedure in this program */
} = 1; /* definition of the program version */
} = 0x30090949; /* remote program number ( must be unique ) */

然后用下列命令产生服务器端函数rdict_srv_func.c:

rpcgen -Ss -o rdict_srv_func.c rdict.x

然后用下列命令产生客户端程序rdict_client.c:

rpcgen -Sc -o rdict_client.c rdict.x

然后用下列命令产生Makefile:

rpcgen -Sm rdict.x > MakefileMakefile文件原内容如下:

# This is a template Makefile generated by rpcgen

# Parameters

CLIENT = rdict_client

SERVER = rdict_server

SOURCES_CLNT.c =

SOURCES_CLNT.h =

SOURCES_SVC.c =

SOURCES_SVC.h =

SOURCES.x = rdict.x

TARGETS_SVC.c = rdict_svc.c rdict_xdr.c

TARGETS_CLNT.c = rdict_clnt.c rdict_xdr.c

TARGETS = rdict.h rdict_xdr.c rdict_clnt.c rdict_svc.c

OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o)

OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o)

# Compiler flags

CFLAGS += -g

LDLIBS += -lnsl

RPCGENFLAGS =

# Targets

all : $(CLIENT) $(SERVER)

$(TARGETS) : $(SOURCES.x)

rpcgen $(RPCGENFLAGS) $(SOURCES.x)

$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) $(TARGETS_CLNT.c)

$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) $(TARGETS_SVC.c)

$(CLIENT) : $(OBJECTS_CLNT)

$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS)

$(SERVER) : $(OBJECTS_SVC)

$(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)

clean:

$(RM) core $(TARGETS) $(OBJECTS_CLNT) $(OBJECTS_SVC) $(CLIENT) $(SERVER)

动手修改Makefile,修改后内容如下:

# This is a template Makefile generated by rpcgen

# Parameters

CLIENT = rdict_client

SERVER = rdict_server

SOURCES_CLNT.c =

SOURCES_CLNT.h =

SOURCES_SVC.c =

SOURCES_SVC.h =

SOURCES.x = rdict.x

TARGETS_SVC.c = rdict_svc.c rdict_xdr.c rdict_srv_func.c

TARGETS_CLNT.c = rdict_clnt.c rdict_xdr.c rdict_client.c

TARGETS = rdict.h rdict_xdr.c rdict_clnt.c rdict_svc.c

OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o)

OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o)

# Compiler flags

CFLAGS += -g

LDLIBS += -lnsl

RPCGENFLAGS =

# Targets

all : $(CLIENT) $(SERVER)

$(TARGETS) : $(SOURCES.x)

rpcgen $(RPCGENFLAGS) $(SOURCES.x)

$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) $(TARGETS_CLNT.c)

$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) $(TARGETS_SVC.c)

$(CLIENT) : $(OBJECTS_CLNT)

$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS)

$(SERVER) : $(OBJECTS_SVC)

$(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)

clean:

$(RM) core $(TARGETS) $(OBJECTS_CLNT) $(OBJECTS_SVC) $(CLIENT) $(SERVER) *~

修改客户端源代码rdict_client.c,把接受用户输入并分析用户输入内容的部分加到程序中来。修改后的代码为:

/*
* This is sample code generated by rpcgen.
* These are only templates and you can use them
* as a guideline for developing your own functions.
*/

#include "rdict.h"

/* ------------------------------------------------------------------

* nextin -- read a command and(possibly) a word from the next input line

* ------------------------------------------------------------------ */

int nextin(char *cmd, char *word)

{

int i, ch;

ch = getc(stdin);

while (isspace(ch)) {

ch = getc(stdin);

} /* end of while */

if (ch == EOF) {

return (-1);

}

*cmd = (char) ch;

ch = getc(stdin);

while (isspace(ch)) {

ch = getc(stdin);

} /* end of while */

if (ch == EOF) {

return (-1);

}

if (ch == '/n') {

return (0);

}

i = 0;

while (!isspace(ch)) {

if (++i > MAXWORD) {

printf("error: word too long./n");

exit(1);

}

*word++ = ch;

ch = getc(stdin);

} /* end of while */

*word = '/0';

return i;

} /* end of nextin */

void rdictprog_1(char *host)

{

CLIENT *clnt;

int *result_1;

char *initw_1_arg;

int *result_2;

char *insertw_1_arg;

int *result_3;

char *deletew_1_arg;

int *result_4;

char *lookupw_1_arg;

#ifndef DEBUG

clnt = clnt_create(host, RDICTPROG, RDICTVERS, "udp");

if (clnt == NULL) {

clnt_pcreateerror(host);

exit(1);

}

#endif /* DEBUG */

char word[MAXWORD + 1]; /* space to hold word from input line */

char cmd;

int wordlen; /* length of input word */

while (1) {

printf("/nPlease input:");

wordlen = nextin(&cmd, word);

if (wordlen < 0) {

exit(0);

}

/* printf("/nYour cmd is:%c, your word is:%s/n", cmd, word); */

switch (cmd) {

case 'I': /* 初始化 */

result_1 = initw_1((void *) &initw_1_arg, clnt);

/* printf("/nYour result is:%d/n", *result_1); */

if (result_1 == (int *) NULL)

clnt_perror(clnt, "call failed");

else

if(*result_1 ==0) printf("Dictionary initialized to empty./n");

else printf("Dictionary have already initialized./n");

break;

case 'i': /* 插入 */

insertw_1_arg = word;

result_2 = insertw_1(&insertw_1_arg, clnt);

/* printf("/nYour result is:%d, your string is:%s(%d)/n", *result_2, insertw_1_arg, strlen(insertw_1_arg)); */

if (result_2 == (int *) NULL)

clnt_perror(clnt, "call failed");

else

printf("%s inserted./n", word);

break;

case 'd': /* 删除 */

deletew_1_arg = word;

result_3 = deletew_1(&deletew_1_arg, clnt);

/* printf("/nYour result is:%d, your string is:%s(%d)/n", *result_3, deletew_1_arg, strlen(deletew_1_arg)); */

if (result_3 == (int *) NULL)

clnt_perror(clnt, "call failed");

else

printf("%s deleted./n", word);

break;

case 'l': /* 查询 */

lookupw_1_arg = word;

result_4 = lookupw_1(&lookupw_1_arg, clnt);

/* printf("/nYour result is:%d, your string is:%s(%d)/n", *result_4, lookupw_1_arg, strlen(lookupw_1_arg)); */

if (result_4 == (int *) NULL)

clnt_perror(clnt, "call failed");

else

if(*result_4 ==0) printf("%s found./n", word);

else printf("%s not found./n", word);

break;

case 'q': /* 退出 */

printf("Program quits./n");

exit(0);

break;

default: /* 非法输入 */

printf("Command %c(%s) invalid./n", cmd, word);

break;

} /* end of switch */

} /* end of while */

#ifndef DEBUG

clnt_destroy(clnt);

#endif /* DEBUG */

}

int main(int argc, char *argv[])

{

char *host;

if (argc < 2) {

printf("usage: %s server_host/n", argv[0]);

exit(1);

}

host = argv[1];

rdictprog_1(host);

exit(0);

}

同时修改服务器端代码rdict_srv_func.c,修改后内容为:

/*
* This is sample code generated by rpcgen.
* These are only templates and you can use them
* as a guideline for developing your own functions.
*/

#include "rdict.h"

char dict[DICTSIZ][MAXWORD + 1]; /* storage for a dictionary of words */

int nwords = 0; /* number of words in the dictionary */

char init_bool = 0;

int initw(void)

{

if(init_bool) return 1;

nwords = 0;

init_bool = 1;

return 0;

} /* end of initw */

/* ------------------------------------------------------------------

* insertw -- insert a word in the dictionary

* ------------------------------------------------------------------ */

int insertw(const char *word)

{

strcpy(dict[nwords%DICTSIZ], word);

nwords++;

return (nwords);

} /* end of insertw */

/* ------------------------------------------------------------------

* deletew -- delete a word from the dictionary

* ------------------------------------------------------------------ */

int deletew(const char *word)

{

int i;

for (i = 0; i < nwords; i++) {

if (strcmp(word, dict[i]) == 0) {

nwords--;

strcpy(dict[i], dict[nwords]);

return (1);

}

} /* end of for */

return (0);

} /* end of deletew */

/* ------------------------------------------------------------------

* lookupw -- look up a word in the dictionary

* ------------------------------------------------------------------ */

int lookupw(const char *word)

{

int i;

for (i = 0; i < nwords; i++) {

if (strcmp(word, dict[i]) == 0) {

return 0;

}

} /* end of for */

return 1;

} /* end of lookupw */

int *initw_1_svc(void *argp, struct svc_req *rqstp)

{

static int result;

/*

* insert server code here

*/

result = initw();

return &result;

}

int *insertw_1_svc(char **argp, struct svc_req *rqstp)

{

static int result;

/*

* insert server code here

*/

result = insertw(*argp);

return &result;

}

int *deletew_1_svc(char **argp, struct svc_req *rqstp)

{

static int result;

/*

* insert server code here

*/

result = deletew(*argp);

return &result;

}

int *lookupw_1_svc(char **argp, struct svc_req *rqstp)

{

static int result;

/*

* insert server code here

*/

result = lookupw(*argp);

return &result;

}

至此,程序做好了。输入一个make命令就可以生成test_server和test_client这两个可执行程序了。

在一台机器上运行./test_server程序,在另外的客户机上运行./test_client server_ip就可以了。这里server_ip是运行着test_server程序的主机的IP地址(本机测试为127.0.0.1)。

另外补充,若启动server出现can not register service:RPC错误,因为ubuntu系统未安装portmap所致,执行命令:sudo apt-get install portmap之后就可以。

只为分享。

原文  http://www.uml.org.cn/embeded/201608171.asp
正文到此结束
Loading...