一种解析HTTP chunked编码数据的方法
技术领域
本发明涉及网络通信领域,特别涉及一种解析HTTP chunked编码数据的方法。
背景技术
HTTP协议的消息格式包含消息首部和消息体。消息首部部分定义了一些属性字段,这些字段向报文接收者提供了重要的信息。其中,Content-Length属性字段表示消息体的长度,该字段有利于数据接收过程的编程实现。然而,对于某些动态生成的数据,消息生成者可能无法立即知悉消息体的总长度,从而不能及时计算Content-Length字段值。使用chunked编码可以回避这一问题。Chunked是HTTP/1.1协议的一种传输编码方式,该传输编码方式将待传输数据切割为多个部分,报文只需提供每个部分的长度。编码后的消息体是一组连续的编码块(chunk),每个编码块包含了传输数据块(chunk-data)及其长度(chunk-size),其格式定义如下:
chunk=chunk-size[chunk-extension]CRLF chunk-data CRLF
其中,chunk-size是chunk-data的长度,为十六进制字符串。CRLF为双字节换行符,其ASCII码值为0x0d0x0a。可选的chunk-extension格式用一组“name=value”字段组成,但RFC2616未对这些字段进行定义,并规定接收者忽略不能识别的字段。
流媒体业务的分发和传输过程使用了HTTP协议,对节目内容进行chunked编码。流服务器通过TCP协议接收报文,解码后,以UDP方式推送给IPQAM,进而发送给终端用户。由于流媒体具有数据量大、传输时间长的特点,流服务器将会对大量数据进行chunked解码操作,因此,chunked解码过程的效率对于流服务器的整体性能至关重要。选择不同的chunked编码解析方式,能够给系统的开发效率、运行性能都能带来相当大的影响。
作为对chunked解析的一种最简单的实现,离线解析方法先将一个完整的HTTP报文通过网络编程技术复制到本地一个连续、单一的应用层缓冲区,再基于这个连续缓冲区根据chunked编码规则提取有效数据,将解析出的数据拷贝到有效内容缓冲区。HTTPchunked编码离线解析法导致解码过程中会产生两次内存拷贝,造成内存占用多、处理延迟高的问题。且离线解析法适合于原型系统开发,并不适合产品开发环境。
发明内容
本发明的目的在于克服现有的HTTP chunked编码离线解析法内存占用多、处理延迟高的缺陷,从而提供一种能够快速解析HTTP chunked编码的方法。
为了实现上述目的,本发明提供了一种解析HTTP chunked编码数据的方法,包括:
步骤1)、定位到所接收的HTTP报文中任一chunk的起始位置;
步骤2)、根据当前的解析状态对chunk中的chunk-size字段的长度进行预测;其中,所述解析状态指一个chunk的读取过程的完成程度;
步骤3)、根据前一步骤所得到的预测长度读取相应长度的chunk-size数据并缓存,对当前缓存的全部chunk-size数据加以分析,根据分析结果判断是否已经完成对整个chunk-size字段的读取,若已完成,执行下一步,否则,基于当前缓存的全部chunk-size数据分析解析状态,并重新执行步骤2);
步骤4)、根据整个chunk-size字段值,读取chunk-data中的数据。
上述技术方案中,在所述的步骤2)中,将当前解析状态下chunk-size字段尚未被读取的字节数可能的最小值作为预测的长度值;包括:
若当前解析状态为“空串”,则chunk-size字段尚未被读取的字节数可能的最小值为5;
若当前解析状态为“已读取1字节”,则chunk-size字段尚未被读取的字节数可能的最小值为4;
若当前解析状态为“已读取2字节”,则chunk-size字段尚未被读取的字节数可能的最小值为3;
若当前解析状态为“已读取3字节且未遭遇字段末尾的CR”,则chunk-size字段尚未被读取的字节数可能的最小值为2;
若当前解析状态为“读到了字段末尾的CR”,则chunk-size字段尚未被读取的字节数可能的最小值为1;
若当前解析状态为“读到了字段末尾的LF”,则chunk-size字段尚未被读取的字节数可能的最小值为0。
上述技术方案中,在所述的步骤3)中,若当前缓存的全部chunk-size数据中已经包含字段末尾的LF,则已经完成对整个chunk-size字段的读取。
上述技术方案中,在所述的步骤3)中,基于当前缓存的全部chunk-size数据分析解析状态包括:
若当前缓存的全部chunk-size数据满足“”,则当前解析状态为“空串”;
若当前缓存的全部chunk-size数据满足“\r”,则当前解析状态为“已读取1字节”;
若当前缓存的全部chunk-size数据满足“\r\n”,则当前解析状态为“已读取2字节”;
若当前缓存的全部chunk-size数据满足“\r\n”[h]*,则当前解析状态为“已读取3字节且未遭遇字段末尾的CR”;
若当前缓存的全部chunk-size数据满足“\r\n”[h]*“\r”,则当前解析状态为“读到了字段末尾的CR”;
若当前缓存的全部chunk-size数据满足“\r\n”[h]*“\r\n”,则当前解析状态为“读到了字段末尾的LF”。
本发明的优点在于:
1、本发明不需要一个完整的应用层缓冲区存放HTTP报文,降低内存占用。
2、本发明减少一次内存拷贝,减小了处理延迟。
附图说明
图1是本发明的解析HTTP chunked编码数据的方法的流程图;
图2是本发明的解析HTTP chunked编码数据的系统框图;
图3-图7是在一个实施例中解析HTTP chunked编码的工作过程示意图。
具体实施方式
在对本发明做详细说明之前,对本发明中所涉及的相关概念做统一描述。
chunk-size字段:与RFC2616中所描述的chunk-size字段相同,还包括该字段之前与之后的回车换行符(即CRLF)。
chunk-data字段:与RFC2616中所描述的chunk-data字段相同。
现结合附图对本发明作进一步的描述。
本发明的方法能够实现对HTTP chunked编码数据的快速解析,参考图1,本发明的方法包括以下步骤:
步骤1)、定位到所接收的HTTP报文中任一chunk的起始位置;
步骤2)、根据当前的解析状态对chunk中的chunk-size字段的长度进行预测;其中,所述解析状态指一个chunk的读取过程的完成程度;
步骤3)、根据前一步骤所得到的预测长度读取相应长度的chunk-size数据并缓存,对当前缓存的全部chunk-size数据加以分析,根据分析结果判断是否已经完成对整个chunk-size字段的读取,若已完成,执行下一步,否则,基于当前缓存的全部chunk-size数据分析解析状态,并重新执行步骤2);
步骤4)、根据整个chunk-size字段值,读取chunk-data中的数据。
在所述的步骤2)中,对chunk中的chunk-size字段的长度进行预测时,需要获取当前解析状态下chunk-size字段尚未被读取的字节数可能的最小值,这一最小值就是预测的长度值。
chunk-size字段在读取过程中共涉及6个解析状态,这6个解析状态与chunk-size字段中尚未被读取的字节数可能的最小值之间的对应关系如下:
表1
上述表格中,[h]*表示0到多个十六进制数字。
在所述的步骤3)中,当读取到字段末尾的LF后,意味着整个chunk-size字段读取完毕。
在所述的步骤3)中,将当前缓存的全部chunk-size数据与之前提到的表1中状态表示式进行比较,根据比较结果确定解析状态。
本发明还提供了一种与上述方法相对应的系统,如图2所示,该系统包括:数据接收模块、有效数据缓存模块、字段缓存模块以及字段长度预测模块。其中,
所述的数据接收模块用于接收网络数据,维护一定量的缓冲区,将已经从网络接收到但尚未被其他模块读取的网络数据缓存于该缓冲区,提供接口供其他模块顺序读取该缓冲区内的数据。其他模块会请求读取若干字节,但实际得到的字节数可能会小于请求的字节数;
所述的有效数据缓存模块用于维护一定量的缓冲区,存放chunked编码的数据经解析后的HTTP报文有效内容;
所述的字段缓存模块用于维护一定量的缓冲区,存放正在被解析的chunk的chunk-size字段已经被读取的部分;
所述的字段长度预测模块用于计算当前chunk的chunk-size字段尚未被读取的字节数可能的最小值。
下面对该系统中的各个模块做进一步的说明。
所述数据接收模块、有效数据缓存模块、字段缓存模块中的缓冲区包括DRAM内存、SRAM内存、Flash EEPROM Memory、本地固态硬盘或机械硬盘提供的存储单元。
所述字段长度预测模块,根据已经读取到的chunk-size字段的内容,归纳解析活动的解析状态,基于这个解析状态推断chunk-size字段尚未被读取的字节数可能的最小值。
为了便于理解,下面参考图3-图7,结合一个具体的实例,对本发明的方法与系统做详细的说明。
(1)如图3所示,假设输入的chunked编码报文(不包含HTTP报头)用C语言风格的字串可表示为“\r\n10\r\n0123456789abcdef\r\n0\r\n”,报文只有1个长度非零的chunk,该chunk包含16字节有效数据。该报文被数据接收模块接收。开始解析第一个chunk。初始状态表示为“”,查阅表1,chunk-size字段剩余字节最小值查表为5。从数据接收模块读取5字节,读到字段缓存模块。相应的结果如图4所示。
(2)此时,读到的数据为“\n10\r”,匹配表1中的状态表示“\r\n”[h]*“\r”。查表知chunk-size字段剩余字节最小值查表为1。从数据接收模块读取1字节,读到字段缓存模块。相应的结果如图5所示。
(3)此时,读到的数据为“\r\n10\r\n”,匹配表1中的状态表示“\r\n”[h]*“\r\n”。查表知chunk-size字段剩余字节最小值查表为0。chunk-size字段读取完成。分析chunk-size字段,发现chunk-data长度为16。从数据接收模块读取16字节,读到有效数据缓存模块。相应的结果如图6所示。进入下一个chunk。
(4)此时,读到的数据为空串,匹配表1中的状态表示“”。查表知chunk-size字段剩余字节最小值查表为5。从数据接收模块读取5字节,读到字段缓存模块。相应的结果如图7所示。
(5)此时,读到的数据为“\r\n0\r\n”,匹配表1中的状态表示“\r\n”[h]*“\r\n”。查表知chunk-size字段剩余字节最小值查表为0。chunk-size字段读取完成。分析chunk-size字段,发现chunk-data长度为0。报文解析结束。
最后所应说明的是,以上实施例仅用以说明本发明的技术方案而非限制。尽管参照实施例对本发明进行了详细说明,本领域的普通技术人员应当理解,对本发明的技术方案进行修改或者等同替换,都不脱离本发明技术方案的精神和范围,其均应涵盖在本发明的权利要求范围当中。