RPC外部数据表示(XDR)
RPC的xdr(外部数据表示)是为了编码(解码)C语言定义的数据,从而使得RPC传输的数据平台无关性。
xdr对C语言常见的类型编码规则在之前已经说过了,参见http://blog.chinaunix.net/u2/87570/showart_2159266.html,对于说明书test.x定义的定义,最终会被rpcgen翻译成支持C语言支持的类型定义,之后test.x就没有任何作用了。
如在test.x中定义
struct data
{
char char_arg;
short short_arg;
long long_arg;
string vstring_arg<128>;
opaque fopaque_arg[3];
char fchar_arg[3];
opoque vopaque_arg<>;
long vlong_arg<>;
};
对应的test.h
struct data {
char char_arg;
short short_arg;
long long_arg;
char *vstring_arg;
char fopaque_arg[3];
char fchar_arg[3];
struct {
u_int vopaque_arg_len;
opoque *vopaque_arg_val;
} vopaque_arg;
struct {
u_int vlong_arg_len;
long *vlong_arg_val;
} vlong_arg;
};
typedef struct data data;
从test.h中可以看到,对于opaque[], char[]的定义,在C语言中对对应char[],而根据xdr的规则,opaque[]编码为固定长度n个字节的序列(会被补全至4字节的倍数);而char[]会被编码成固定长度n个4字节元素序列。怎么这里都是char[]???
别急,编码规则在头文件中是没有显现出来的,根据说明书中定义,rpcgen会生成相应的方法对各种数据进行编码,而这些编码方法均在test_xdr.c中。
再看test_xdr.c
bool_t
xdr_data (XDR *xdrs, data *objp)
{
//xdr_char转换char型数据类型到其外部数据表示,每个char占4个字节,unsigned char,short, unsigned short, int, unsigned int的编码格式均相同
if (!xdr_char (xdrs, &objp->char_arg))
return FALSE;
if (!xdr_short (xdrs, &objp->short_arg))
return FALSE;
if (!xdr_long (xdrs, &objp->long_arg))
return FALSE;
//字符串类型,序列前包含字符串的长度,总长度补全至4的倍数
if (!xdr_string (xdrs, &objp->vstring_arg, 128))
return FALSE;
//xdr_opaque用以转换固定长度不透明序列
if (!xdr_opaque (xdrs, objp->fopaque_arg, 3))
return FALSE;
//xdr_vector用以转换固定长度透明数据类型序列
if (!xdr_vector (xdrs, (char *)objp->fchar_arg, 3,
sizeof (char), (xdrproc_t) xdr_char))
return FALSE;
//xdr_array用于转换不定长度的序列
if (!xdr_array (xdrs, (char **)&objp->vopaque_arg.vopaque_arg_val, (u_int *) &objp->vopaque_arg.vopaque_arg_len, ~0,
sizeof (opoque), (xdrproc_t) xdr_opoque))
return FALSE;
if (!xdr_array (xdrs, (char **)&objp->vlong_arg.vlong_arg_val, (u_int *) &objp->vlong_arg.vlong_arg_len, ~0,
sizeof (long), (xdrproc_t) xdr_long))
return FALSE;
return TRUE;
}
从test_xdr.c中可以看出,opaque[],char[]是分别是通过xdr_opaque,xdr_vector编码(需要传递各个元素编码的方法,如此例中的xdr_char()),故在xdr表示中opaque[],char[]是不同的。
对于opaque<>, datatype<>都是通过xdr_array实现的,同样根据传递过来的编码方法xdr_opaque, xdr_long,它们被编码成不同的格式。