C语言的柔性数组运用解析

简化版应用场景:有一串不同类型,不同大小的数据需要传输,某通信协议支持x byte的数据包长度,将这一串数据封装成不大于x byte的数据包依次传输,如何设计数据包的封装和解析?

设计数据包:为了方便对端解析,设计数据包有头部和数据两段,头部用结构体的元素表示,需要什么信息则添加一个元素定义,数据段用柔性数组,是为了保证头部和数据段得内存保持连续,如下所示:

typedef struct node_s {
    int type;        /* 头部,可根据实际情况添加元素 */
    int len;         /* 头部,标识数据段已使用的长度 */
    char value[0];   /* 数据段,柔性数组 */
} node_t;

所以,柔性数组实现扩展长度的结构体一句话概括就是:在结构体的最后加上一个长度为零的char数组

用sizeof(node_t)可以发现,柔性数组是不占内存空间的。


如何添加一段数据到数据包呢?

1,初始化:

#define MAX_INFO_SIZE (x - sizeof(node_t))
node_t *nodeinfo;
char *mark;
node_info = (node_t *)malloc(sizeof(node_t) + MAX_INFO_SIZE);
if (node_info == NULL) {
    mem_error();
}
memset(node_info, 0, sizeof(node_t) + MAX_INFO_SIZE);
node_info->type = your_type;
node_info->len = 0;
mark = &node_info->value;


即是:申请一段内存,初始化,将数据段的标志位mark指向value地址,还没有添加数据,所以len为0;

2,添加数据

for (data = x; data < y; data = next(x)) { 	/* 遍历那串数据,简化版 */
    len = get_data_len(data);
    if (node_info->len + len <= MAX_INFO_SIZE) {
        memcpy(mark, data, len);
        mark += len;
        node_info->len += len;
    } else {
        send(node_info); 			/* 调用某协议发送出数据,简化版 */

        memset(node_info, 0, sizeof(node_t) + MAX_INFO_SIZE);
        node_info->type = your_type;
        node_info->len = 0;
        mark = &node_info->value;
        memcpy(mark, data, len);
        mark += len;
        node_info->len += len; 
    }
}
send(node_info); 				/* 发送最后一个数据包 */


添加数据的操作即是:将数据拷贝到数据段,记录添加的长度,移动标记位以便下次添加。如果数据达到数据包最大值,发送掉这个包,然后继续添加操作。

这样,每个不大于x byte的数据包都填充好了data数据,并且利用通信机制发送到了另一个地方。

那“另一个地方”接收到了这个不大于x byte的数据包,如何从数据包里解析出data数据来呢?

3,解析数据

假设某台机器得到了这个数据包,要查看数据包里每个data的内容,如何解析?

node_t *node_info;
char *buf;
int len;
node_t *node_info;
get_info(node_info);         /* 让node_info得到了那个不大于x byte的数据包,简化版 */
for (buf = node_info->value; buf < node_info->value + node_info->len; buf += len) {
    data = (data_t *)buf;    /* 从数据包里取到了一个data */
    op(data);                /* 查看数据包,简化版 */
    len = get_data_len(data); 
}


以上,利用柔性数组构造一个数据包,并进行封包,发包,解包的操作就完成了!

在实际生产应用中,要对数据包的头部扩展,其他的每一个操作都不会像例子的伪代码那样简单,但原理是一样的。


如果没有用过柔性数组的童鞋,可以思考一下:

为什么最后一个原始是0元素的数组而不是指针呢?假如不是C99怎么办?


---------------------------------这是分割线-------------------------------------

第一次写博客,实在不知道写什么东西,也发现即使是自己经常用,已经习以为常的小知识点,要用文字阐述清除,也是非常困难滴,文中肯定有很多不足,欢迎大家指正!


评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值