Chinaunix首页 | 论坛 | 博客
  • 博客访问: 81874
  • 博文数量: 12
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 331
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-17 19:34
文章分类

全部博文(12)

文章存档

2014年(1)

2013年(11)

我的朋友

分类: LINUX

2013-07-01 09:44:35

一、概述
本文主要是在linux下面编写一个简单的RPC的程序。在linux下面编写RPC程序的最简单的办法就是使用rpcgen工具,它通过一个规格说明文件rpcsth.x(这个文件爱你可以自由命名,但是必须要以.x结尾)。然后通过rpcgen rpcsth.x命令来生成rpcsth.h、rpcsth_xdr.c、rpcsth_clnt.c和rpcsth_svc.c四个文件。
二、Hello word程序
1)首先编写test.x文件,代码如下:

点击(此处)折叠或打开

  1. program RTEST
  2. {
  3.     version RDICTVER
  4.     {
  5.         int TESTVOID(void) = 1;
  6.         int TESTSTRING(string) = 2;
  7.     } = 1;
  8. } = 0x12345;
在这里,函数的说明基本和下面的说明是一致的,只是char *变成了string。另外要给每个定义的函数赋一个值。
2)生成源文件
   在linux下面输入rpcgen test.x命令,然后你就会发现生成了桑文件:test.h 、test_clnt.c  和test_svc.c。由于没有在test.x中定义结构体,所以没有生成test_xdr.c文件。
打开test.h会发现如下几行函数:

点击(此处)折叠或打开

  1. define TESTVOID 1
  2. extern int * testvoid_1(void *, CLIENT *);
  3. extern int * testvoid_1_svc(void *, struct svc_req *);
  4. #define TESTSTRING 2
  5. extern int * teststring_1(char **, CLIENT *);
  6. extern int * teststring_1_svc(char **, struct svc_req *);
在test.x中定义的函数被转换成了小写,并加上了版本号1.其中teststring_1对应的是client端的stub通信例程,即test_clnt.c。而teststring_1_svc.c对应的是server端的stub接口例程,需要我们自己来完成。
3)编写客户端常规函数和主函数(testclient.c
testclient.c的代码如下;

点击(此处)折叠或打开

  1. #include "test.h"
  2. #define RMACHINE "127.0.0.1"//表示的是服务器端的ip地址,在这里主要是声明的是本地的

  3. CLIENT *handle;

  4. int testvoid();
  5. int teststring(char * szTest);

  6. int main(int argc,char *argv)
  7. {
  8.     char szTest[100];
  9.     strcpy(szTest,"hello world!");
  10.     handle = clnt_create(RMACHINE,RTEST,RDICTVER,"tcp");

  11.     if(handle == 0){
  12.       printf("error to create the handle!\n");
  13.       return 1;
  14.     }
  15.     testvoid();
  16.     teststring(szTest);
  17.     return 0;
  18. }

  19. int teststring(char *szTest)
  20. {
  21.    char ** pszArg;
  22.    int *ret;
  23.    pszArg = &szTest;
  24.    ret = teststring_1(pszArg,handle);

  25.    return (ret ==0?0:*ret);
  26. }

  27. int testvoid(void)
  28. {
  29.     int *ret;
  30.     ret = testvoid_1(0,handle);
  31.     return(ret ==0?0:*ret);
  32. }
4)编写server端的stub接口例程(test_srvint.c函数
test_srvint.c函数的代码如下:

点击(此处)折叠或打开

  1. #include "test.h"
  2. static int ret;

  3. int *testvoid_1_svc(void *v,struct svc_req *s)
  4. {
  5.     ret = testvoid();
  6.     return &ret;
  7. }

  8. int *teststring_1_svc(char **pszstring,struct svc_req *s)
  9. {
  10.    ret = teststring(*pszstring);
  11.    return &ret;
  12. }
5)编写server端常规函数(testserver.c函数
testserver.c函数的代码如下:

点击(此处)折叠或打开

  1. #include "test.h"

  2. int testvoid(void)
  3. {
  4.    printf("void !\n");
  5.    return 0;
  6. }

  7. int teststring(char *szTest)
  8. {
  9.     printf("Tthe test string is :%s\n",szTest);
  10.     return 0;
  11. }
6)Makefile文件如下(自己写的makefile很戳的

点击(此处)折叠或打开

  1. TAR = testclient testserver

  2. all:$(TAR)

  3. testclient:testclient.o test_clnt.o
  4.     cc -O3 -o testclient testclient.o test_clnt.o
  5. testclient.o:testclient.c
  6.     cc -O3 -o testclient.o -c testclient.c
  7. test_clnt.o:test_clnt.c
  8.     cc -O3 -o test_clnt.o -c test_clnt.c

  9. testserver:testserver.o test_srvint.o test_svc.o
  10.     cc -O3 $^ -o $@
  11. test_svc.o:test_svc.c
  12.     cc -O3 -o test_svc.o -c test_svc.c
  13. test_srvint.o:test_srvint.c
  14.      cc -O3 -o test_srvint.o -c test_srvint.c
  15. test_server.o:test_server.c
  16.     cc -O3 -o test_server.o -c test_server.c

  17. .PHONY:clean
  18. clean:
  19.     rm *.o $(TAR)

三、运行程序
直接运行testserver和testclient即可。
可能遇到的问题如下:
(1)运行testserver的时候出现:Cannot register service: RPC: Unable to receive; errno = Connection refused。出现这个错误的原因是因为服务器端没有开启端口映射的功能。开启portmap就可以了:
sudo /etc/init.d/portmap restart
当然,如果没有安装portmap,那么需要安装portmap直接执行下面的命令即可:
sudo apt-get install portmap
2)程序运行的时候需要在root权限的情况下运行。
如果一切顺利的话就可以在服务器端看到我么熟悉的hello word输出了。




阅读(1983) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~