使用glibc xdr对结构体进行编解码
作者:互联网
glibc 中的 rpc/xdr.h 提供了很多 xdr_xxx() 接口,可以用一种跨平台的方式对任意数据进行编码和表示。下面介绍如何对结构体数据进行跨平台的编码和解码,主要涉及以下几个步骤:
1)使用 rpc 语言定义结构体(类似于 thrift 中的 IDL 文件),使用 rpcgen 生成对应的 .h 和 .c 文件
2)使用 xdrstdio_create() 初始化 XDR 对象,并调用上述文件自动生成的接口对结构体数据进行编码,得到编码后的内存 buffer
3)使用 xdrmem_create() 和上述内存 buffer,初始化 XDR 对象,并调用上述文件自动生成的接口对 buffer 进行解码,得到编码前的结构体数据
使用示例如下:
1)在 request.x 文件中定义 struct request 结构体:
struct request {
char session_id[25];
char name[33];
char data[1024];
int data_len;
};
2)使用 rpcgen 生成 .h 和 .c 文件:
$ rpcgen request.x
$ ls -l
total 12
-rw-r--r-- 1 root root 564 Mar 6 22:34 request.h
-rw-r--r-- 1 root root 91 Mar 6 22:34 request.x
-rw-r--r-- 1 root root 577 Mar 6 22:34 request_xdr.c
自动生成的 request.h 文件内容:
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#ifndef _REQUEST_H_RPCGEN
#define _REQUEST_H_RPCGEN
#include <rpc/rpc.h>
#ifdef __cplusplus
extern "C" {
#endif
struct request {
char session_id[25];
char name[33];
char data[1024];
int data_len;
};
typedef struct request request;
/* the xdr functions */
#if defined(__STDC__) || defined(__cplusplus)
extern bool_t xdr_request (XDR *, request*);
#else /* K&R C */
extern bool_t xdr_request ();
#endif /* K&R C */
#ifdef __cplusplus
}
#endif
#endif /* !_REQUEST_H_RPCGEN */
自动生成的 request_xdr.c 文件内容:
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#include "request.h"
bool_t
xdr_request (XDR *xdrs, request *objp)
{
register int32_t *buf;
int i;
if (!xdr_vector (xdrs, (char *)objp->session_id, 25,
sizeof (char), (xdrproc_t) xdr_char))
return FALSE;
if (!xdr_vector (xdrs, (char *)objp->name, 33,
sizeof (char), (xdrproc_t) xdr_char))
return FALSE;
if (!xdr_vector (xdrs, (char *)objp->data, 1024,
sizeof (char), (xdrproc_t) xdr_char))
return FALSE;
if (!xdr_int (xdrs, &objp->data_len))
return FALSE;
return TRUE;
}
3 )编码 和 解码示例:
#include <rpc/xdr.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "request.h"
char *encode(struct request *req, size_t *sizep)
{
char *buf = NULL;
FILE *fp = open_memstream(&buf, sizep);
XDR xdr;
xdrstdio_create(&xdr, fp, XDR_ENCODE);
int ret = xdr_request(&xdr, req);
fclose(fp);
return buf;
}
void decode(char *buf, int size, struct request *req)
{
FILE *fp = fmemopen(buf, size, "r");
XDR xdr;
xdrstdio_create(&xdr, fp, XDR_DECODE);
int ret = xdr_request(&xdr, req);
fclose(fp);
}
int main(void)
{
struct request req;
strcpy(req.session_id, "abcd2021");
strcpy(req.name, "Jimmy");
strcpy(req.data, "hello, world!");
req.data_len = strlen("hello, world!") + 1;
char *buf = NULL;
size_t size = 0;
buf = encode(&req, &size);
printf("buffer size after encode: %d\n", size);
struct request _req;
decode(buf, size, &_req);
printf("decoded session_id: %s\n", _req.session_id);
printf("decoded name: %s\n", _req.name);
printf("decoded data: %s\n", _req.data);
printf("decoded data_len: %d\n", _req.data_len);
free(buf);
return 0;
}
运行结果:
buffer size after encode: 4332
decoded session_id: abcd2021
decoded name: Jimmy
decoded data: hello, world!
decoded data_len: 14
标签:编解码,glibc,req,request,char,xdr,data,size 来源: https://blog.csdn.net/choumin/article/details/114461137