LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1984|回复: 3

Linux RPC测试

[复制链接]
发表于 2009-9-25 10:18:35 | 显示全部楼层 |阅读模式
RPC是glibc提供的函数参数/返回值封装服务, 并将封装结果通过网络传到服务器.

RPC服务端首先要启动portmapper服务.

测试一个简单的RPC传输示例, 先定义一个模板文件test.x

  1. program TESTPROG{
  2.         version VERSION{
  3.                 int int_echo(int)=1;
  4.                 int get_str_len(string)=2;
  5.                 int add ( int, int ) = 3;
  6.         }=1;
  7. }=30000;
复制代码


内含3个函数, 注意其中一个有2个参数.

然后可以用rpcgen生成一个Makefile:

  1. rpcgen -a -N test.x
复制代码


这会生成Makefile, 客户端和服务端的程序, 和函数示例.

我们手工修改一下Makefile
  1. # This is a template Makefile generated by rpcgen

  2. # Parameters

  3. CLIENT = test_client
  4. SERVER = test_server

  5. SOURCES_CLNT.c =
  6. SOURCES_CLNT.h =
  7. SOURCES_SVC.c =
  8. SOURCES_SVC.h =
  9. SOURCES.x = test.x

  10. TARGETS_SVC.c = test_svc.c test_server.c test_xdr.c
  11. TARGETS_CLNT.c = test_clnt.c test_client.c test_xdr.c
  12. TARGETS = test.h test_xdr.c test_clnt.c test_svc.c

  13. OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o)
  14. OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o)
  15. # Compiler flags

  16. CFLAGS += -g -pipe
  17. LDLIBS += -lnsl
  18. RPCGENFLAGS = -N

  19. # Targets

  20. all : $(CLIENT) $(SERVER)

  21. $(TARGETS) : $(SOURCES.x)
  22.         rpcgen $(RPCGENFLAGS) $(SOURCES.x)

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

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

  25. $(CLIENT) : $(OBJECTS_CLNT)
  26.         $(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS)

  27. $(SERVER) : $(OBJECTS_SVC)
  28.         $(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)

  29. clean:
  30.          $(RM) core $(TARGETS) $(OBJECTS_CLNT) $(OBJECTS_SVC) $(CLIENT) $(SERVER)
复制代码



修改test_server.c服务端的处理函数, 提供3种服务:

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

  6. #include "test.h"

  7. int *
  8. int_echo_1_svc(int arg1,  struct svc_req *rqstp)
  9. {
  10.         static int  result;

  11.         //echo.
  12.         result=arg1;
  13.         printf("[RPC1] source=%d, echo=%d\n", arg1, result);

  14.         return &result;
  15. }

  16. int *
  17. get_str_len_1_svc(char *arg1,  struct svc_req *rqstp)
  18. {
  19.         static int  result;

  20.         //get strlen.
  21.         result=strlen(arg1);
  22.         printf("[PRC2] str=%s, len=%d\n", arg1, result);
  23.         return &result;
  24. }

  25. int *
  26. add_1_svc(int arg1, int arg2,  struct svc_req *rqstp)
  27. {
  28.         static int  result;

  29.         result=arg1+arg2;
  30.         printf("[RPC3] %d+%d=%d\n", arg1, arg2, result);
  31.         return &result;
  32. }
复制代码


客户端test_client.c, 调用这三种服务:

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

  6. #include "test.h"


  7. void
  8. testprog_1(char *host)
  9. {
  10.         CLIENT *clnt;
  11.         int  *result_1;
  12.         int int_echo_1_arg1=55;
  13.         int  *result_2;
  14.         char *get_str_len_1_arg1="Hello, world";
  15.         int  *result_3;
  16.         int add_1_arg1=10;
  17.         int add_1_arg2=20;

  18.         clnt = clnt_create (host, TESTPROG, VERSION, "udp");
  19.         if (clnt == NULL) {
  20.                 clnt_pcreateerror (host);
  21.                 exit (1);
  22.         }

  23.         result_1 = int_echo_1(int_echo_1_arg1, clnt);
  24.         if (result_1 == (int *) NULL) {
  25.                 clnt_perror (clnt, "call failed");
  26.         }
  27.         else
  28.                 printf("[PRC1] echo %d, source %d\n", *result_1,
  29.                         int_echo_1_arg1);

  30.         result_2 = get_str_len_1(get_str_len_1_arg1, clnt);
  31.         if (result_2 == (int *) NULL) {
  32.                 clnt_perror (clnt, "call failed");
  33.         }
  34.         else
  35.                 printf("[RPC2] return %d, should %d\n", *result_2,
  36.                         strlen(get_str_len_1_arg1));
  37.         result_3 = add_1(add_1_arg1, add_1_arg2, clnt);
  38.         if (result_3 == (int *) NULL) {
  39.                 clnt_perror (clnt, "call failed");
  40.         }
  41.         else
  42.                 printf("[PRC3] %d+%d=%d\n", add_1_arg1, add_1_arg2,
  43.                         *result_3);
  44.         clnt_destroy (clnt);
  45. }
复制代码



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

正是我们期望的.

------------------------------------------
原创作品, 张力辉 <swordhui@263.net>
------------------------------------------
发表于 2009-9-25 17:44:58 | 显示全部楼层
swordhui兄好!
是我给加的精华。顺便问些背景知识,RPC是如何确保安全性有一套机制吗?
回复 支持 反对

使用道具 举报

发表于 2009-9-25 18:43:00 | 显示全部楼层
这么懒的方法,好!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-3-31 15:21:59 | 显示全部楼层
Post by realtang;2030252
swordhui兄好!
是我给加的精华。顺便问些背景知识,RPC是如何确保安全性有一套机制吗?

好久不来了,今天偶然发现居然留了篇精,谢谢:flash:

我对RPC安全性了解不深,有空翻翻glibc的源码,看看对rpc安全性方面做了什么工作。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表