转自:
http://www.justwinit.cn/post/3960/
RPC是glibc提供的函数参数/返回值封装服务, 并将封装结果通过网络传到服务器.
RPC服务端首先要启动portmapper服务.
测试一个简单的RPC传输示例, 先定义一个模板文件test.x
program TESTPROG{
version VERSION{
int int_echo(int)=1;
int get_str_len(string)=2;
int add ( int, int ) = 3;
}=1;
}=30000;
内含3个函数, 注意其中一个有2个参数.
然后可以用rpcgen生成一个Makefile:
rpcgen -a -N test.x
这会生成Makefile, 客户端和服务端的程序, 和函数示例.
我们手工修改一下Makefile
# This is a template Makefile generated by rpcgen
# Parameters
CLIENT = test_client
SERVER = test_server
SOURCES_CLNT.c =
SOURCES_CLNT.h =
SOURCES_SVC.c =
SOURCES_SVC.h =
SOURCES.x = test.x
TARGETS_SVC.c = test_svc.c test_server.c test_xdr.c
TARGETS_CLNT.c = test_clnt.c test_client.c test_xdr.c
TARGETS = test.h test_xdr.c test_clnt.c test_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 -pipe
LDLIBS += -lnsl
RPCGENFLAGS = -N
# 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)
修改test_server.c服务端的处理函数, 提供3种服务:
/*
* 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 "test.h"
int *
int_echo_1_svc(int arg1, struct svc_req *rqstp)
{
static int result;
//echo.
result=arg1;
printf("[RPC1] source=%d, echo=%d\n", arg1, result);
return &result;
}
int *
get_str_len_1_svc(char *arg1, struct svc_req *rqstp)
{
static int result;
//get strlen.
result=strlen(arg1);
printf("[PRC2] str=%s, len=%d\n", arg1, result);
return &result;
}
int *
add_1_svc(int arg1, int arg2, struct svc_req *rqstp)
{
static int result;
result=arg1+arg2;
printf("[RPC3] %d+%d=%d\n", arg1, arg2, result);
return &result;
}
客户端test_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 "test.h"
void
testprog_1(char *host)
{
CLIENT *clnt;
int *result_1;
int int_echo_1_arg1=55;
int *result_2;
char *get_str_len_1_arg1="Hello, world";
int *result_3;
int add_1_arg1=10;
int add_1_arg2=20;
clnt = clnt_create (host, TESTPROG, VERSION, "udp");
if (clnt == NULL) {
clnt_pcreateerror (host);
exit (1);
}
result_1 = int_echo_1(int_echo_1_arg1, clnt);
if (result_1 == (int *) NULL) {
clnt_perror (clnt, "call failed");
}
else
printf("[PRC1] echo %d, source %d\n", *result_1,
int_echo_1_arg1);
result_2 = get_str_len_1(get_str_len_1_arg1, clnt);
if (result_2 == (int *) NULL) {
clnt_perror (clnt, "call failed");
}
else
printf("[RPC2] return %d, should %d\n", *result_2,
strlen(get_str_len_1_arg1));
result_3 = add_1(add_1_arg1, add_1_arg2, clnt);
if (result_3 == (int *) NULL) {
clnt_perror (clnt, "call failed");
}
else
printf("[PRC3] %d+%d=%d\n", add_1_arg1, add_1_arg2,
*result_3);
clnt_destroy (clnt);
}
OK, 可以调用make了.
生成可执行程序test_server和test_client.
我们启动./test_server, 用rpcinfo看看:
$rpcinfo -p 127.0.0.1
program vers proto port
100000 2 tcp 111 portmapper
30000 1 udp 36307
30000 1 tcp 34883
Bingo! 启动成功.
再开个终端, 尝试一下调用.
./test_client 127.0.0.1
[PRC1] echo 55, source 55
[RPC2] return 12, should 12
[PRC3] 10+20=30
正是我们期望的.
Add By:Jackxiang
make -f Makefile.test