`

流数据缓冲库设计方案

 
阅读更多

流数据缓冲库设计方案

流数据的不对称

所谓流数据,指通道里的数据是串行的,没有分隔符的。流数据到达接收方后,如果没有一个机制来分割流数据,则犹如一堆乱码。这里的机制指发送方和接收方所商定的通信协议,例如一个基本消息(协议规定的最小单位)是以什么字节开头,以什么字节结尾,每个字节的含义是什么。

TCP和串口是面向数据流的传输方式。发送方发送一次的数据,接收方可能分多次接收(read返回);也可能发送方分多次发送的数据,接收方一次性接收了,这种现象称为粘包,在一个发送方情况下发送数据过快,以及在多个发送方的情况下,粘包很频繁。特别是对于非阻塞read,这种现象就更加频繁了。对于阻塞read,发送方一次发送的数据,接收方一次性接收的可能性比较大,但也不排除分多次接收的可能。

接收方的难言之隐

通过上面的分析,在面向流的数据传输中,发送方与接收方相应的发送和接收操作不是一一对应的,接收方需要把所有接收到的数据“保存”下来,然后根据协议来“分割”数据流,从而“挖掘”出其中的消息。对于“保存”,接收方有诸多难言之隐:

#数据保存在什么数据结构的buffer中?

#从这个buffer中取出部分流数据进行解析,解析完后不能构成一个完整消息的剩余数据如何放回这个buffer?

#一个向buffer中存数据,一个向buffer中取数据,同步效率如何保证?

#因为read操作是在不断的进行的, 是一次性还是多次为buffer分配内存,是分配固定还是动态大小的内存?

需求需求

这样,对于这种普遍存在的传输方式中的接收方而言,APP希望能够对buffer的操作是透明、简单和通用的。这个buffer犹如是一个大小和内容动态变化的文件,里面有其所需要消息的流数据。APP的操作流程是打开这个文件,读取适量大小的流数据,然后“分割”和“挖掘”出消息,当确实“挖掘”不出有意义的消息了,则将剩余的流数据写回文件。

现在就让我来介绍下这样的一个工具的原理及实现,它用来保存流连接中接收方所接收到的数据,并且重点的是它是可扩展性,高效性的,线程安全的。

基本原理

采用双向循环链表作为存储结构,将每次收到的数据构成一个元素,采用固定元素个数的循环链表,并且只在初始化中申请一次内存,这大大提高了效率。

尾指针用来元素入链表,头指针用来元素出链表。当接收方收到数据后,将数据组成元素并放入链表;用户程序在取数据时,会指定期望最多取数据的长度(n),会有一个临时指针,以头指针所在的位置,向尾指针方向移动,直到第i个元素(小于头指针)的元素的数据长度加上前i-1个元素的长度,大于n,而前i-1个元素的数据长度m小于n,则返回前i-1个元素的总长度m以及前i-1个元素的数据组成的bit字符串。

同时支持将数据“反刍”进链表的操作,仍以上面的例子数据为例,如果返回的i-1个元素的m个字节中,“分割”的结果是:只有3/4m个字节是一个完整的消息,剩余的1/4m个字节是不完整的。这时,需要反刍回链表,以使下次取数据能得到完整的消息。

在取数据的过程中,头指针实际上没有真正进行移动,只是有一个临时指针指向了第i个元素,在取完数据后,用户程序会告之真正accept的数据长度h(<=m),如果h等于m,则头指针直接移动到临时指针的位置;如果h小于m,则移动头指针,直到第j个节点(<=i),前j个节点的长度k大于等于h,而前j-1个节点的长度g小于h,那么第一步将尾指针移动到第j个节点处,第二步,将第j个元素的数据的后面的k-h位移动到数据的前k-h位。

例如接收到的数据逻辑顺序为:

Abcdefghijkl

分四次接收,并放入循环链表中(用尾指针放):

(head)abc def gh ijkl(rear)

取10个字节的数据(从头指针开始取):

Abcdefghij

如果只有4个字节abcd组成了消息,则只接收4个字节,进行反刍:

(1)第一个节点abc,由于长度3小于4,则此节点不是分界点元素

(2)第二个节点defg,由于全两个元素长度3+3=6大于4,则此节点为分界点元素,将def中的后6-4=2个元素fg,移动到前6-4=2位,则分界点元素为ef

(3)将尾指针移动到分界点节点

最后链表如下:

(head)ef gh ijkl(rear)

数据结构定义

Typedef struct DOUBLECIRCLELIST

{

Char*data;

Intrllen; // real data length

Intbflen; //this buffer block length

structDOUBLECIRCLELIST* prev;

struct DOUBLECIRCLELIST* next;

}DoubleCircleList;

接口定义

Int FdbInit( int blockNum, int blockSize );

Int FdbPutData( char* ptData, int ptLen );

Int FdbGetData( char* gtData, int* gtLen );

Int FdbAcceptLength( int apLen );

//second steps

Int FdbPutDataRemoc( char* ptData, intptLen ); //Enlarge the size of one block

Int FdbEnlargeInit( int blockNum, intblockSize );// Enlarge the number of the list elements

固定元素个数的环形双向链表头尾指针说明:

1、head和rear之间的节点代表是具体的有数据的节点,包括head和rear这两个节点,也就是[head, rear]是有数据的。

2、链表满的条件是:rear->next == head;

3、链表只有一个节点的条件是:rear==head

4、链表为空的条件是:rear == NULL,head != NULL

5、在构造环形链表时,head->prev == reat&& rear->next= head, 则始终是满的

6、在构建完环形链表后,rear = NULL

分享到:
评论

相关推荐

    SQL Server 2008商业智能完美解决方案 1/3

    14.5.1 数据流缓冲区 342 14.5.2 同步数据流输出 346 14.5.3 异步数据流输出 346 14.6 日志提供程序 346 14.7 部署Integration Services包 347 14.7.1 包配置 347 14.7.2 包部署选项 348 14.8 小结 348 第15章 用...

    SQL Server 2008商业智能完美解决方案 3/3

    14.5.1 数据流缓冲区 342 14.5.2 同步数据流输出 346 14.5.3 异步数据流输出 346 14.6 日志提供程序 346 14.7 部署Integration Services包 347 14.7.1 包配置 347 14.7.2 包部署选项 348 14.8 小结 348 第15章 用...

    SQL Server 2008商业智能完美解决方案 2/3

    14.5.1 数据流缓冲区 342 14.5.2 同步数据流输出 346 14.5.3 异步数据流输出 346 14.6 日志提供程序 346 14.7 部署Integration Services包 347 14.7.1 包配置 347 14.7.2 包部署选项 348 14.8 小结 348 第15章 用...

    SQL Server 2008 商业智能完美解决方案(3)

    14.5.1 数据流缓冲区 342 14.5.2 同步数据流输出 346 14.5.3 异步数据流输出 346 14.6 日志提供程序 346 14.7 部署Integration Services包 347 14.7.1 包配置 347 14.7.2 包部署选项 348 14.8 小结 348 第...

    易语言程序免安装版下载

    修改扩展界面支持库一,禁止透明标签在父窗口刷新时自动刷新,以解决其导致窗口刷新缓冲的问题。 8. 改进应用接口支持库中“设置屏幕分辨率”命令。 9. 修改外部数据库在“表中记录数为零”时可能导致程序崩溃的...

    蓝焰设计站图文管理系统

    同时对系统的开发原理、系统的功能特点和设计方案进行了介绍。 【关键词】ASP.NET ADO.NET 新闻 管理 数据库 随着Internet的普及,越来越多的企业建立了自己的WWW网站,企业通过网站可以展示产品,发布最新动态,与...

    asp.net知识库

    与DotNet数据对象结合的自定义数据对象设计 (二) 数据集合与DataTable 与DotNet数据对象结合的自定义数据对象设计 (一) 数据对象与DataRow ASP.NET中大结果集的分页[翻译] .net 2.0 访问Oracle --与Sql Server的...

    软件工程-理论与实践(许家珆)习题答案

    在进行了可行性分析后,需求分析就只需要解决目标系统的设计方案。(×) 2. SA法是面向数据流,建立在数据封闭原则上的需求分析方法。(√) 3. HIPO法既是需求分析方法,又是软件设计方法。(√) 4. 在面向对象的...

    开涛高可用高并发-亿级流量核心技术

    16.6.11 多种压测方案 338 16.7 遇到的一些坑和问题 339 16.7.1 SSD性能差 339 16.7.2 键值存储选型压测 340 16.7.3 数据量大时JIMDB同步不动 342 16.7.4 切换主从 342 16.7.5 分片配置 342 16.7.6 模板元数据存储...

    58mm USB 热敏打印机(写字库源代码+字库软件+USB 电脑打印机模式等)-电路方案

    USB 数据中断: 分析数据流,见函数 PTR_Data_Receive(), 遇图形点阵数据流,写入环形缓冲区。遇命令立即执行,或为执行做好准备。若有打印命令或走纸命令,就把 “走纸行数” 通过全局变量 StepIncrease 传给主循环...

    JAVA上百实例源码以及开源项目源代码

     Java数据压缩与传输实例,可以学习一下实例化套按字、得到文件输入流、压缩输入流、文件输出流、实例化缓冲区、写入数据到文件、关闭输入流、关闭套接字关闭输出流、输出错误信息等Java编程小技巧。 Java数组倒置...

    计算机应用基础18秋在线作业2【满分答案】.docx

    计算机各部件之间有两股信息流,即数据流和控制流 D.对信息(即各种形式的数据)进行收集、储存、加工与传输等一系列活动的总称为实时控制 正确答案:"[D]" 21.在Word中进行"页面设置",主要是设置页面的( ) A.字符数/...

    【东师】计算机应用基础21秋学期在线作业2【69783】.doc

    计算机各部件之间有两股信息流,即数据流和控制流 D.对信息(即各种形式的数据)进行收集、储存、加工与传输等一系列活动的总称为实时 控制 答案:D 21.在Word中进行"页面设置",主要是设置页面的() A.字符数/行数、页...

    计算机应用基础【东师】19秋在线作业23.doc

    计算机各部件之间有两股信息流,即数据流和控制流 D.对信息(即各种形式的数据)进行收集、储存、加工与传输等一系列活动的总称为实时 控制 【参考选择是】:D 21.在Word中进行"页面设置",主要是设置页面的( ) A.字符...

    matlab代码做游戏-Hsuching-Dev-Stars:我自己的超赞清单!

    -使用数据流图进行计算以进行可扩展的机器学习 -内存有效的序列化库 -JavaScript中的Protobuf实现 -协议缓冲区-Google的数据交换格式 -2014要做的一些事的记录 -将Oculus Rift与网络链接的实用程序和JavaScript库 ...

    matlab代码做游戏-Hsuching-Dev-Starts:我的GitHub明星精选清单!

    matlab代码做游戏很棒的星星 我的GitHub明星精选清单! 产生者 内容 [GCC机器说明](#gcc机器说明) [Vim脚本](#vim脚本) C -重力编程语言 -Aerospike数据库服务器–闪存优化的内存中...-协议缓冲区-Google的数据

    明日科技C#开发入门及项目实战

    实例158 使用缓冲流复制文件 实例159 文件批量更名 实例160 复制文件时显示复制进度 实例161 对指定文件夹中的文件进行分类存储 实例162 将文本文件转换成网页文件 实例163 伪装文件夹 实例164 word目录提取工具 第...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    SQL(Structured Query Language)结构化查询语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。同时也是数据库脚本文件的扩展名。  SQL语言主要包含5个部分  数据定义...

    JAVA上百实例源码以及开源项目

     Java数据压缩与传输实例,可以学习一下实例化套按字、得到文件输入流、压缩输入流、文件输出流、实例化缓冲区、写入数据到文件、关闭输入流、关闭套接字关闭输出流、输出错误信息等Java编程小技巧。 Java数组倒置...

    C++ Primer中文版(第5版)李普曼 等著 pdf 1/3

     15.9.1 面向对象的解决方案 563  15.9.2 Query_base类和Query类 567  15.9.3 派生类 568  15.9.4 eval函数 571  小结 575  术语表 575  第16章 模板与泛型编程 577  16.1 定义模板 578  16.1.1 函数模板 ...

Global site tag (gtag.js) - Google Analytics