使用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);
	fflush(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);
	fflush(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

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值