linux下rpc 编程

linux下的RPC编程,关于RPC的协议以及工作原理这里就不说了,没了解的可以先网上查找了解下,下面就一个简单例子来说明RPC,例子是这样的:客户端向服务器端发出命令,然后服务端回应相应的数据。

 1 #define MAXLEN 1500 
 2 #define RPC_HELLO 0x80000088
 3 enum type {
 4     rpc_invalid,
 5     rpc_hello,
 6     rpc_goodbye,
 7     rpc_number
 8 };  
 9 
10 struct _hello_t {
11     enum type op; 
12     int status;
13     char data[MAXLEN];
14 };
15 
16 typedef struct _hello_t hello_t;
17 
18 program helloProg {
19     version helloVers {
20         hello_t rpc_hello( hello_t ) = 1;
21     } = 1;
22 } = RPC_HELLO; 

编写了hello.x文件,上面可以看到RPC由程序号(program number),程序版本号(program version number),过程号(procedure number)唯一确定的。hello_t rpc_hello ( hello_t ) 就是我们定义的接口,

定义好后,在linux利用rpc解析工具rpcgen对.x文件进行处理得到想要的文件,如下

dgq@t468 rpc $ ls 
hello.x
dgq@t468 rpc $ rpcgen hello.x 
dgq@t468 rpc $ ls
hello.h  hello.x  hello_clnt.c  hello_svc.c  hello_xdr.c
dgq@t468 rpc $ rpcgen -Sc -o hello_client.c hello.x
dgq@t468 rpc $ rpcgen -Ss -o hello_server.c hello.x
dgq@t468 rpc $ rpcgen -Sm hello.x > Makefile       
dgq@t468 rpc $ ls
Makefile  hello.h  hello.x  hello_client.c  hello_clnt.c  hello_server.c  hello_svc.c  hello_xdr.c

生成的这些文件,主要关注hello_client.c hello_server.c,内容如下

hello_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 
 7 #include "hello.h"
 8 
 9 
10 void
11 helloprog_1(char *host)
12 {
13     CLIENT *clnt;
14     hello_t  *result_1;
15     hello_t  rpc_hello_1_arg;
16 
17 #ifndef DEBUG
18     clnt = clnt_create (host, helloProg, helloVers, "udp");
19     if (clnt == NULL) {
20         clnt_pcreateerror (host);
21         exit (1);
22     }   
23 #endif  /* DEBUG */
24 
25     result_1 = rpc_hello_1(&rpc_hello_1_arg, clnt);
26     if (result_1 == (hello_t *) NULL) {
27         clnt_perror (clnt, "call failed");
28     }   
29 #ifndef DEBUG
30     clnt_destroy (clnt);
31 #endif   /* DEBUG */
32 }
33 
34 
35 int
36 main (int argc, char *argv[])
37 {
38     char *host;
39 
40     if (argc < 2) {
41         printf ("usage: %s server_host\n", argv[0]);
42         exit (1);
43     }
44     host = argv[1];
45     helloprog_1 (host);
46 exit (0);
47 }

hello_server.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 
  7 #include "hello.h"
  8 
  9 hello_t *
 10 rpc_hello_1_svc(hello_t *argp, struct svc_req *rqstp)
 11 {
 12     static hello_t  result;
 13 
 14     /*
 15      * insert server code here
 16      */
 17 
 18     return &result;
 19 }
~                                                                                                                                
~                 

然后对这两个文件进行修改后,如下

 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 
 7 #include "hello.h"
 8 #include <string.h>
 9 #include <stdlib.h>
10 
11 void
12 helloprog_1(char *host, int flag)
13 {
14         CLIENT *clnt;
15         hello_t  *result_1;
16         hello_t  data;
17 
18         bzero(&data, sizeof data);
19 #ifndef DEBUG
20         clnt = clnt_create (host, helloProg, helloVers, "udp");
21         if (clnt == NULL) {
22                 clnt_pcreateerror (host);
23                 exit (1);
24         }
25 #endif  /* DEBUG */
26 
27         if (flag == 1){
28                 data.op = rpc_hello;
29         }
30         if (flag == 2){
31                 data.op = rpc_goodbye;
32         }
33         result_1 = rpc_hello_1(&data, clnt);
34         if (result_1 == (hello_t *) NULL) {
35                 clnt_perror (clnt, "call failed");
36         }
37         printf("%s", result_1->data);
38 
39 #ifndef DEBUG
40         clnt_destroy (clnt);
41 #endif   /* DEBUG */
42 }
43 
44 
45 int
46 main (int argc, char *argv[])
47 {
48         char *host;
49         int flag;
50         if (argc < 3) {
51                 printf ("usage: %s server_host\n", argv[0]);
52                 exit (1);
53         }
54         host = argv[1];
55         flag = atoi(argv[2]);
56         helloprog_1 (host, flag);
57         exit (0);
58 
59 }

 

 

 1 #include "hello.h"
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <time.h>
 5 
 6 hello_t *
 7 rpc_hello_1_svc(hello_t *argp, struct svc_req *rqstp)
 8 {
 9         static hello_t  result;
10 
11         struct timeval tv;
12 
13         gettimeofday(&tv, NULL);
14 
15 
16         /*
17          * insert server code here
18          */
19         switch(argp->op){
20                 case 1:
21                         sprintf(result.data, "%s:Hello 2013!\n%s", getenv("USER"), ctime(&tv.tv_sec));
22                         break;
23                 case 2:
24                         sprintf(result.data, "%s:Goodbye 2012!\n%s", getenv("USER"), ctime(&tv.tv_sec));
25                         break;
26                 default:
27                         sprintf(result.data, "unkown commond!\n");
28         }
29 
30         return &result;
31 }

然后对Makefile进行修改,如下

 1 # This is a template Makefile generated by rpcgen
 2 
 3 # Parameters
 4 
 5 CLIENT = hello_client
 6 SERVER = hello_server
 7 
 8 SOURCES_CLNT.c =
 9 SOURCES_CLNT.h =
10 SOURCES_SVC.c =
11 SOURCES_SVC.h =
12 SOURCES.x = hello.x
13 
14 TARGETS_SVC.c = hello_svc.c   hello_xdr.c hello_server.c
15 TARGETS_CLNT.c = hello_clnt.c   hello_xdr.c hello_client.c
16 TARGETS = hello.h hello_xdr.c hello_clnt.c hello_svc.c
17 
18 OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o)
19 OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o)
20 # Compiler flags 
21 
22 CFLAGS += -g
23 LDLIBS += -lnsl
24 RPCGENFLAGS =
25 
26 # Targets 
27 
28 all : $(CLIENT) $(SERVER)
29 
30 $(TARGETS) : $(SOURCES.x)
31         rpcgen $(RPCGENFLAGS) $(SOURCES.x)
32 
33 $(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) $(TARGETS_CLNT.c)

 

然后make就会产生可执行文件,hello_client 和 hello_server, 启动hello_server作为后台运行,运行hello_client 等到结果如下:

 

root@t468 rpc # ./hello_server &
[1] 28379
root@t468 rpc # ./hello_client 127.0.0.1 1
root:Hello 2013!
Sun Jan 13 13:24:58 2013
root@t468 rpc # ./hello_client 127.0.0.1 2
root:Goodbye 2012!
Sun Jan 13 13:25:00 2013
root@t468 rpc # 

这里把客户端和服务端都运行在同一台机子上,使用回环地址来请求,可以看到能正常工作,但在实际项目中没有这么简单,比如对timeout,用udp还是tcp都有要求,不过掌握了基本的,也复杂不到哪里去。

 

 

 

 

 

posted on 2013-01-13 13:47  流川仙道  阅读(1298)  评论(0编辑  收藏  举报

导航