📄 567.htm
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>CTerm非常精华下载</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" width="100%" cellspacing="0" cellpadding="0" height="577">
<tr><td width="32%" rowspan="3" height="123"><img src="DDl_back.jpg" width="300" height="129" alt="DDl_back.jpg"></td><td width="30%" background="DDl_back2.jpg" height="35"><p align="center"><a href="http://apue.dhs.org"><font face="黑体"><big><big>apue</big></big></font></a></td></tr>
<tr>
<td width="68%" background="DDl_back2.jpg" height="44"><big><big><font face="黑体"><p align="center"> ● UNIX网络编程 (BM: clown) </font></big></big></td></tr>
<tr>
<td width="68%" height="44" bgcolor="#000000"><font face="黑体"><big><big><p align="center"></big></big><a href="http://cterm.163.net"><img src="banner.gif" width="400" height="60" alt="banner.gif"border="0"></a></font></td>
</tr>
<tr><td width="100%" colspan="2" height="100" align="center" valign="top"><br><p align="center">[<a href="index.htm">回到开始</a>][<a href="15.htm">上一层</a>][<a href="568.htm">下一篇</a>]
<hr><p align="left"><small>发信人: cloudsky (小四), 信区: Security <br>
标 题: RPC/XDR/NFS系列之----外部数据表示 <br>
发信站: 武汉白云黄鹤站 (Wed Feb 23 17:30:45 2000), 站内信件 <br>
现在让我们回头来看看<<RPC/XDR/NFS系列之----RPC编程初战(1)>>中 <br>
"rpcgen产生的XDR转换文件"小节里的那个函数 <br>
bool_t xdr_example ( XDR * xdrs, example * objp ) <br>
{ <br>
register long * buf; <br>
if ( !xdr_int( xdrs, &objp->exfield1 ) ) <br>
{ <br>
return FALSE; /* 转换失败返回FALSE */ <br>
} <br>
if ( !xdr_char( xdrs, &objp->exfield2 ) ) <br>
{ <br>
return FALSE; <br>
} <br>
return TRUE; /* 转换成功则返回TRUE */ <br>
} <br>
struct example <br>
{ <br>
int exfield1; <br>
char exfield2; <br>
}; <br>
}; <br>
显然,XDR处理C的struct的时候就是简单地依次处理每个成员,具体到这里 <br>
就是分别调用了xdr_int和xdr_char转换例程,很好理解,是不是? <br>
★ XDR库中的转换例程(Redhat) <br>
可以查看/usr/include/rpc/xdr.h,找到所有可用的XDR转换例程 <br>
/* <br>
* These are the "generic" xdr routines. <br>
* None of these can have const applied because it's not possible to <br>
* know whether the call is a read or a write to the passed parameter <br>
* also, the XDR structure is always updated by some of these calls. <br>
*/ <br>
extern bool_t xdr_void __P ((void)); <br>
extern bool_t xdr_short __P ((XDR *__xdrs, short *__sp)); <br>
extern bool_t xdr_u_short __P ((XDR *__xdrs, u_short *__usp)); <br>
extern bool_t xdr_int __P ((XDR *__xdrs, int *__ip)); <br>
extern bool_t xdr_u_int __P ((XDR *__xdrs, u_int *__up)); <br>
extern bool_t xdr_long __P ((XDR *__xdrs, long *__lp)); <br>
extern bool_t xdr_u_long __P ((XDR *__xdrs, u_long *__ulp)); <br>
extern bool_t xdr_hyper __P ((XDR *__xdrs, quad_t *__llp)); <br>
extern bool_t xdr_u_hyper __P ((XDR *__xdrs, u_quad_t *__ullp)); <br>
extern bool_t xdr_longlong_t __P ((XDR *__xdrs, quad_t *__llp)); <br>
extern bool_t xdr_u_longlong_t __P ((XDR *__xdrs, u_quad_t *__ullp)); <br>
extern bool_t xdr_int8_t __P ((XDR *__xdrs, int8_t *__ip)); <br>
extern bool_t xdr_uint8_t __P ((XDR *__xdrs, uint8_t *__up)); <br>
extern bool_t xdr_int16_t __P ((XDR *__xdrs, int16_t *__ip)); <br>
extern bool_t xdr_uint16_t __P ((XDR *__xdrs, uint16_t *__up)); <br>
extern bool_t xdr_int32_t __P ((XDR *__xdrs, int32_t *__ip)); <br>
extern bool_t xdr_uint32_t __P ((XDR *__xdrs, uint32_t *__up)); <br>
extern bool_t xdr_int64_t __P ((XDR *__xdrs, int64_t *__ip)); <br>
extern bool_t xdr_uint64_t __P ((XDR *__xdrs, uint64_t *__up)); <br>
extern bool_t xdr_bool __P ((XDR *__xdrs, bool_t *__bp)); <br>
extern bool_t xdr_enum __P ((XDR *__xdrs, enum_t *__ep)); <br>
extern bool_t xdr_array __P ((XDR * _xdrs, caddr_t *__addrp, u_int *__sizep, <br>
<br>
u_int __maxsize, u_int __elsize, <br>
xdrproc_t __elproc)); <br>
extern bool_t xdr_bytes __P ((XDR *__xdrs, char **__cpp, u_int *__sizep, <br>
u_int __maxsize)); <br>
extern bool_t xdr_opaque __P ((XDR *__xdrs, caddr_t __cp, u_int __cnt)); <br>
extern bool_t xdr_string __P ((XDR *__xdrs, char **__cpp, u_int __maxsize)); <br>
<br>
extern bool_t xdr_union __P ((XDR *__xdrs, enum_t *__dscmp, char *__unp, <br>
__const struct xdr_discrim *__choices, <br>
xdrproc_t dfault)); <br>
extern bool_t xdr_char __P ((XDR *__xdrs, char *__cp)); <br>
extern bool_t xdr_u_char __P ((XDR *__xdrs, u_char *__cp)); <br>
extern bool_t xdr_vector __P ((XDR *__xdrs, char *__basep, u_int __nelem, <br>
u_int __elemsize, xdrproc_t __xdr_elem)); <br>
extern bool_t xdr_float __P ((XDR *__xdrs, float *__fp)); <br>
extern bool_t xdr_double __P ((XDR *__xdrs, double *__dp)); <br>
extern bool_t xdr_reference __P ((XDR *__xdrs, caddr_t *__xpp, u_int __size, <br>
<br>
xdrproc_t __proc)); <br>
extern bool_t xdr_pointer __P ((XDR *__xdrs, char **__objpp, <br>
u_int __obj_size, xdrproc_t __xdr_obj)); <br>
extern bool_t xdr_wrapstring __P ((XDR *__xdrs, char **__cpp)); <br>
extern u_long xdr_sizeof __P ((xdrproc_t, void *)); <br>
为了形成一个RPC报文,应用程序要为报文中的每个数据项调用XDR转换例程。应用程序 <br>
<br>
发送最终生成的XDR流,接收方必须颠倒整个过程。 <br>
接收方调用xdrmem_create初始化用于存放XDR流的内存缓冲区,将接收到的报文放入该 <br>
<br>
缓冲区。XDR流自己记录了转换方向(应该是保存在XDR流首部中),以确定是编码还是解 <br>
码, <br>
xdrmem_create函数的第三个参数指明了XDR例程的转换方向。 <br>
xdrmem_create( xdrs, buf, BUFSIZE, XDR_DECODE ); <br>
一旦接收方已经建立用于解码的XDR流,就可以调用转换例程从XDR流中获得相应类型的 <br>
数 <br>
据,并将该数据转换成本地数据表示: <br>
int i; /* 使用本地表示的整数 */ <br>
... ... /* XDR流已经初始化成解码 */ <br>
xdr_int( xdrs, &i ); /* 从XDR流中提取整数 */ <br>
这里有别于BSD的htons和ntohs转换例程,XDR转换例程不需要单独指定转换方向, <br>
转换方向是在创建XDR流时指定的,XDR转换例程会检查XDR流中保存的这个转换方向。 <br>
★ xdrstdio_create函数 <br>
使用xdrmem_create创建的XDR流允许应用程序向网络发送数据前把大量数据转换成 <br>
外部数据表示。各个数据项逗被转换并放入缓冲区后,应用程序将调用一个象write <br>
这样的I/O函数以便在一个TCP/IP连接上将其发送出去。 <br>
可以让XDR转换例程每次转换完毕一个数据项就自动发送出去。为此需要介绍 <br>
xdrstdio_create函数。 <br>
在/usr/include/rpc/xdr.h中有如下定义: <br>
/* XDR using stdio library */ <br>
extern void xdrstdio_create __P ((XDR *__xdrs, FILE *__file, enum xdr_op __x <br>
op)) <br>
; <br>
首先建立一个标准的socket,然后用fdopen获得该socket的I/O流表示,然后调用 <br>
xdrstdio_create函数初始化一个XDR流。针对如此创建的XDR流调用XDR转换例程, <br>
会自动完成一个带缓冲的read/write操作。应用程序可以调用Unix标准I/O函数 <br>
对I/O流操作,比如仅仅转换了几个字节就希望输出,可以调用fflush函数。 <br>
★ xdrrec_create函数,XDR流与UDP socket <br>
XDR流与TCP socket可以很好结合,因为二者都使用了抽象的流概念。为了和UDP socke <br>
t <br>
结合,创建XDR流时需要调用xdrrec_create函数。 <br>
在/usr/include/rpc/xdr.h中有如下定义: <br>
/* XDR pseudo records for tcp */ <br>
extern void xdrrec_create __P ((XDR *__xdrs, u_int __sendsize, <br>
u_int __recvsize, caddr_t __tcp_handle, <br>
int (*__readit) (char *, char *, int), <br>
int (*__writeit) (char *, char *, int))); <br>
/* make end of xdr record */ <br>
extern bool_t xdrrec_endofrecord __P ((XDR *__xdrs, bool_t __sendnow)); <br>
/* move to beginning of next record */ <br>
extern bool_t xdrrec_skiprecord __P ((XDR *__xdrs)); <br>
/* true if no more input */ <br>
extern bool_t xdrrec_eof __P ((XDR *__xdrs)); <br>
注意到xdrrec_create函数有两个形参readit和writeit。每次调用XDR转换例程将本地 <br>
表示转换成外部表示时,转换例程将检查缓冲区是否还有空间容纳新数据,如果缓冲区 <br>
<br>
满,转换例程调用writeit发送缓冲区已有内容,为新数据腾出空间。类似,每次调用 <br>
XDR转换例程将外部表示转换成本地表示时,转换例程将检查缓冲区是否含有数据,如 <br>
果缓冲区空,转换例程调用readit获得更多数据到缓冲区。 <br>
为使XDR流与UDP socket结合,调用xdrrec_create创建一个面向记录的XDR流,readit <br>
/writeit对应read/write或者recv/send。应用程序填满缓冲区时,转换例程调用send <br>
用单个UDP数据报发送缓冲区内容。应用程序调用转换例程获取数据时,转换例程调用 <br>
recv获取下一个入UDP数据报,并放入缓冲区中。 <br>
面向记录的XDR流上可以使用xdrrec_endofrecord、xdrrec_skiprecord、xdrrec_eof <br>
函数。 <br>
★ 相关RFC以及参考资料 <br>
RFC 1014 <<XDR: External Data Representation Standard>> <br>
它是Sun Microsystems 公司定义的XDR编码和转换例程。 <br>
RFC 1832 <br>
新版本,这是一个建议标准。 <br>
至于更多的信息应该参考<<solaris网络编程指南>>,我曾经有全套 <br>
solaris的书籍来着,可惜北上前送给同学,太多太重啦,sigh <br>
Douglas E. Comer & David L. Stevens <br>
<< Internetworking With TCP/IP Vol III >> <br>
W.Richard Stevens <br>
<< TCP/IP Illustrated Volume I >> <br>
我的建议是不要看中文翻译版,而是直接看英文原版,许多地方翻译走样。 <br>
scz < mailto: cloudsky@263.net > <br>
2000.02.21 13:59 (待续) <br>
-- <br>
我问飘逝的风:来迟了? <br>
风感慨:是的,他们已经宣战。 <br>
我问苏醒的大地:还有希望么? <br>
大地揉了揉眼睛:还有,还有无数代的少年。 <br>
我问长空中的英魂:你们相信? <br>
英魂带着笑意离去:相信,希望还在。 <br>
</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="15.htm">上一层</a>][<a href="568.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -