博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据循环缓冲区算法
阅读量:6439 次
发布时间:2019-06-23

本文共 6016 字,大约阅读时间需要 20 分钟。

hot3.png

使用方法:

  1. 创建循环缓冲区create_cb
  2. 在获得数据的地方调用write_cb把数据写入缓冲区中
  3. 获得数据帧get_frame,获取符合数据协议帧头和帧尾的数据
/* * cycle_buf_frame.h * *  Created on: 2017年7月31日 *      Author: C */#ifndef MAIN_CYCLE_BUF_FRAME_H_#define MAIN_CYCLE_BUF_FRAME_H_#include 
#include
#include
#include
#define u8 unsigned char#define u16 unsigned short#define u32 unsigned int#define CB_OK 0#define CB_FULL 1#define CB_MALLOC_FAIL 2#define CB_DATA_ERR 3#define CB_NO_VALID 4#define CB_READ_NOENOUGH 5#define CB_INVALID 6#define CB_NO_FRAME 7#define CB_LACK_SPACE 8#define CB_READ_POS_ERR 9#define CB_READ_ERR 10#define MAX_CB_LEN 65534/*定义数据头尾长度1个字节*/#define PTL_HT_LENGTH 1/*固定数据头,高字节在前*/#define PTL_HEAD 'a'/*固定数据尾,高字节在前*/#define PTL_TAIL 'z'typedef enum { /*请求类型*/ REQUEST=0, /*响应类型*/ RESPONESE=1, /*无响应请求类型*/ NONE_RESPONESE=2,}data_types;typedef enum { /*控灯命令*/ CMD_LED=0X0000,}data_cmd;typedef struct { /*数据头,指向第一个数据所在的位置*/ u16 head; /*数据类型:请求,响应,P2P。。。。*/ data_types types; /*命令字*/ data_cmd cmd; /*数据内容长度*/ u16 data_len; /*数据内容*/ void *data; /*CRC效验*/ u16 crc; /*数据尾,指向下一个即将写入数据的位置*/ u16 tail;}data_packge;typedef struct { /*数据头*/ u16 head; /*数据尾*/ u16 tail; /*数据长度*/ u16 len; /*数据体长度即缓冲区长度*/ u16 blen; /*数据体*/ u8* data;}cycle_buffer;u8 creat_cb(cycle_buffer* cb,u16 len);u8 get_frame(cycle_buffer* cb,u8* data,u16* len);u8 read_cb(cycle_buffer* cb,u16 pos,u8* data,u16 len);u8 write_cb(cycle_buffer* cb,u8* wlen,u8* data,u16 len);void cb_test(void);#endif /* MAIN_CYCLE_BUF_FRAME_H_ */
/* * cycle_buf_frame.c * *  Created on: 2017年7月31日 *      Author: C */#include "cycle_buf_frame.h"u8 creat_cb(cycle_buffer* cb,u16 len){    cb->data=malloc(len);    if(cb->data==NULL)        return CB_MALLOC_FAIL;    cb->head=0;    cb->head=0;    cb->tail=0;    cb->len=0;    cb->blen=len;  return CB_OK;}/****************************************************************************//--函数名称:write_cb//--函数功能:写数据到缓冲区//--函数参数:cb   目标缓冲区                            :wlen 已写入数数据长度                            :data 将要写入的数据                            :len  将要写入的数据长度//--返回数据:返回写状态****************************************************************************/u8 write_cb(cycle_buffer* cb,u8* wlen,u8* data,u16 len){    u16 i;    /*写缓冲区*/    for(i=0;i
len<=cb->blen) { cb->data[cb->tail]=data[i]; cb->len++; cb->tail++; /*判断是否已写到数据数组尾*/ if(cb->tail>=cb->blen) { cb->tail=0; } } else { *wlen=i; return CB_FULL; } } *wlen=len; return CB_OK;}/****************************************************************************//--函数名称:read_cb//--函数功能:从缓冲区中读取数据//--函数参数:cb 目标缓冲区 :pos 开始读取的位置,相对于缓冲区基地址的位置 :data 读取数据保存位置 :len 读取数据长度//--返回数据:返回读状态****************************************************************************/u8 read_cb(cycle_buffer* cb,u16 pos,u8* data,u16 len){ u16 i,temp=pos; /*判断缓冲区是否未分配空间*/ if(cb->data==NULL) return CB_INVALID; /*判断pos位置是否处于head到尾之间*/ if(cb->tail>=cb->head) { if(pos
head||pos>=cb->tail) return CB_READ_POS_ERR; } else { if(pos>=cb->tail&&pos
head) return CB_READ_POS_ERR; } /*判断读长度是否大于pos位置到数据尾的数据长度*/ if(cb->tail>=pos) { if(len>(cb->tail-pos)) return CB_READ_NOENOUGH; } if(cb->tail
(cb->blen-pos+cb->tail)) return CB_READ_NOENOUGH; } for(i=0;i
data[temp]; if(temp>cb->blen-1) temp=0; else temp++; } /*将指针赋值给data*/ //data=&cb->data[pos]; return CB_OK;}/****************************************************************************//--函数名称:get_frame//--函数功能:根据数据协议中的帧头和帧尾获取有效帧,并删除帧前的无效数据//--函数参数:cb 目标缓冲区 len 读取到帧的长度//--返回数据:返回读状态****************************************************************************/u8 get_frame(cycle_buffer* cb,u8* data,u16* len){ u16 i,head_pos,tail_pos,temp_pos=cb->head; u8 temp_data[PTL_HT_LENGTH]; u8 find_head=0; u32 temp_num=0; signed char m; for(i=0;i
len-PTL_HT_LENGTH+1;i++) { /*读两个字节*/ if(CB_OK!=read_cb(cb,temp_pos,temp_data,PTL_HT_LENGTH)) return CB_READ_ERR; /*把宏定义的数据头转换成字符数组*/ temp_num=0; for(m=PTL_HT_LENGTH-1;m>=0;m--) { temp_num=temp_num+(temp_data[PTL_HT_LENGTH-1-m]<<(8*m)); } /*判断是否为数据头*/ if(PTL_HEAD==temp_num) { /*记录数据头的位置/更新数据头位置*/ head_pos=temp_pos; find_head++; } /*已找到数据头,再找数据尾*/ if(find_head>0) { /*判断是否为数据尾*/ if(PTL_TAIL==temp_num) { /*找到了数据头,也找到了数据尾*/ /*记录数据尾的位置*/ tail_pos=temp_pos; /*计算帧数据长度*/ if(head_pos
data[head_pos],*len); } else { *len=cb->blen-head_pos+tail_pos+PTL_HT_LENGTH; /*copy数据*/ memcpy(data,&cb->data[head_pos],cb->blen-head_pos); memcpy((data+cb->blen-head_pos),&cb->data[0],tail_pos+PTL_HT_LENGTH); } /*计算剩余数据长度*/ if(cb->head<=head_pos) { /*剩余数据=初始数据-头前无用数据-读走数据*/ cb->len=cb->len-(head_pos-cb->head)-*len; } else { /*剩余数据=初始数据-头前无用数据-读走数据*/ cb->len=cb->len-(cb->blen-cb->head+head_pos)-*len; } /*数据取出后,重置数据头位置*/ if(tail_pos+PTL_HT_LENGTH>=cb->blen) cb->head=cb->blen-(tail_pos+PTL_HT_LENGTH); else cb->head=tail_pos+PTL_HT_LENGTH; return CB_OK; } } /*数据读取位置后移*/ if(temp_pos==cb->blen-1) temp_pos=0; else temp_pos++; } /*读完整个缓冲区未获得完整帧*/ if(find_head>0) { /*重置缓冲区头*/ cb->head=head_pos; /*计算剩余数据长度*/ cb->len=cb->len-(head_pos-cb->head); } else { /*重置整个缓冲区*/ cb->head=cb->tail=cb->len=0; } *len=0; return CB_NO_FRAME;}void cb_test(){ u8 wlen,data1[50],data[50]="rzrabceddzccab"; u16 len; cycle_buffer cb; creat_cb(&cb,50); write_cb(&cb,&wlen,data,14); while(1) { while(get_frame(&cb,data1,&len)==CB_OK) { printf("frame data len %d is:%.*s\n\n",len,len, data1); Sleep(100); } write_cb(&cb,&wlen,data,14); }}

转载于:https://my.oschina.net/u/2345008/blog/892817

你可能感兴趣的文章
发布一个 Linux 下的 C++ 多线程库
查看>>
大数据分布式架构单点故障详解(Hdfs+Yarn+HBase+Spark+Storm)构建HA高可用架构
查看>>
通过Stetho在Chrome上调试Android App
查看>>
presto集群安装&整合hive|mysql|jdbc
查看>>
工行企业网银“您的数据签名有误请联系当地工行”解决办法
查看>>
关于namespace的一点点心得体会(2017年8月3日14:55:37)
查看>>
使用Markdown记录文字
查看>>
Linux TCP 链接状态
查看>>
类的属性、类的方法、类的内置方法
查看>>
Python序列类型
查看>>
再谈ThinkPHP
查看>>
Hibernate问题浅析
查看>>
出现访问apache资源直接下载php文件的解决办法-----yum 安装 php mysql
查看>>
七种Mysql表类型
查看>>
归并与归并排序
查看>>
linux和windows互传文件、用户配置文件和密码配置文件、用户组管理、用户管理...
查看>>
spark 应用程序性能优化经验
查看>>
基于Zabbix IPMI监控服务器硬件状况
查看>>
Go语言之并发资源竞争
查看>>
GNS帧中继配置,帧中继环境搭建
查看>>