Linux RPC编程的几点体会
Linux下面的RPC模型是SUN RPC (ONC RPC),使用了XDR来编码/解码数据。gcc提供了一些标准数据类型的XDR filter(比如整型,浮点型,字符串等)。对于自定义数据类型,则需要自己编写XDR filter来处理。
你可以使用rpcgen来帮你自动生成xdr filter,但是,该工具需要你提供一个 .x 文件。我在实际使用的过程中,遇到了一些问题,解决问题的过程中有了一些体会。
(1) xdr_string 无法处理C++的string类型,XDR里面的string都是C style的,这点需要注意。
(2) 在C里面,指针可以用来访问数组,但是,在XDR中则不能简单的混为一谈。比如:
有一个数据结构st:
-
struct st {
-
int a;
-
int b;
-
};
-
-
struct xxx {
-
struct st *buf;
-
int c;
-
};
通过rpcgen生成的 XDR filter 中使用 xdr_pointer,xxx.buf 只能传递一个struct st。如果想要传递一个 struct st 数组,则需要使用 xdr_array(可变size的数组)或 xdr_vector (固定size的数组,与 C++ 标准库里面的vector不是一个概念!),.x文件的写法有些不一样!
(3) 我曾经遇到了一个问题,XDR filter 直接返回失败!通过clnt_perrno得到的错误信息是:Can't encode arguments! 花了很多时间才发现,是因为给数据结构里面的一个string(char *)类型的成员传递了空值,导致xdr_string总是失败!
(4) RPC 传输的数据结构长度有限制,通过UDP方式传输,数据结构长度最大为8K,超过就会失败。如果要传输大的数据结构,可以使用TCP方式。
(5) 曾经遇到一个奇怪的问题,在某台机器上某个rpc调用会出现错误,但是在别的机器上面没有问题,最后发现是因为系统时间是错误的。
我发现,出错的rpc调用是return了系统的时间戳。只要系统的时间在2038年某天以后,rpc就会出错。rpc 调用里面使用了一个long型来传递时间(根据time_t的定义,long型就足够了),系统是64位系统,所以应该没有溢出。我试着将数据类型改为unsigned long。错误消失了。问题的根源没有找到。
下面是测试代码:
date.x:
-
program DATE_PROG {
-
version DATE_VERS {
-
long GET_DATE(void) = 1;
-
} = 1;
-
} = 0x20000002;
date_server.c:
点击(此处)折叠或打开
-
#include <time.h>
-
#include "date.h"
-
-
long * get_date_1_svc(void *argp, struct svc_req *rqstp)
-
{
-
static long result;
-
-
result = time((long *)0);
-
-
return &result;
-
}
date_client.c:
点击(此处)折叠或打开
-
#include "date.h"
-
-
-
void date_prog_1(char *host)
-
{
-
CLIENT *clnt;
-
long *result_1;
-
char *get_date_1_arg;
-
-
clnt = clnt_create(host, DATE_PROG, DATE_VERS, "udp");
-
if (clnt == NULL) {
-
clnt_pcreateerror(host);
-
exit(1);
-
}
-
-
result_1 = get_date_1((void*)&get_date_1_arg, clnt);
-
if (result_1 == (long *)NULL) {
-
clnt_perror(clnt, "call failed");
-
exit(1);
-
}
-
printf("time on host %s: %ld\n", host, *result_1);
-
-
clnt_destroy(clnt);
-
}
-
-
-
int main (int argc, char *argv[])
-
{
-
char *host;
-
-
if (argc < 2) {
-
printf ("usage: %s server_host\n", argv[0]);
-
exit (1);
-
}
-
-
host = argv[1];
-
date_prog_1(host);
-
exit (0);
-
}
Makefile:
点击(此处)折叠或打开
-
BIN = server client
-
GEN = date_clnt.c date_svc.c date_xdr.c date.h
-
RPCGEN = rpcgen
-
-
CFLAGS = -Wall -O -DRPC_SVC_FG #-g
-
#LDLIBS =
-
#LDFLAGS =
-
-
all: $(BIN)
-
-
client: date_client.o date_clnt.o
-
$(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
-
server: date_server.o date_svc.o
-
$(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
-
-
date_client.o: date.h
-
date_server.o: date.h
-
-
$(GEN): date.x
-
$(RPCGEN) -C $^
-
clean:
-
$(RM) *.o $(BIN) $(GEN)
阅读(10755) | 评论(0) | 转发(3) |