admin管理员组

文章数量:1530300

2024年7月12日发(作者:)

HTTP1.1中CHUNKED编码方式传输数据的解析

隐网项目”的图片下载模块需要与HTTP Response报文打交道,由于使用的是C++,没有java

中十分好用的httpclient,所以打算自己实现。之前考虑的比较简单,假设请求的文件是jpeg文件,所以

在收到数据之后,只考虑跳过响应报文的HEADER部分加rnrn四个字节后,直接把剩余的数据写到文

件中。测试过程中,发现有相当一部分图片不能正常打开,总是比服务器多了几个字节;打印输出响应报

文后发现头中并没有我们通常所见的Content-Length域来指明报文体的长度,反而是多了Transfer –

Encoding域。上网查阅http1.1协议后,发现通常情况下,Transfer-Encoding域的值应当为chunked,

表明采用chunked编码方式来进行报文体的传输。协议中关于这个字段的具体解释如下:

一般HTTP通信时会使用是Content-Length头信息性来指定小,但是有时候无法确定信息大小,就要使

用trunked编码动态的提供body内容的长度。进行Chunked编码传输的HTTP数据要在消息头部设置:

Transfer-Encoding: chunked表示Content Body将用chunked编码传输内容。Chunked编码一般使

用若干个chunk串连而成,最后由一个标明长度为0的chunk标示结束。每个chunk分为头部和正文两

部分,头部内容指定下一段正文的字符总数(非零开头的十六进制的数字)和数量单位(一般不写,表示字

节).正文部分就是指定长度的实际内容,两部分之间用回车换行(CRLF)隔开。在最后一个长度为0的chunk

中的内容是称为footer的内容,是一些附加的Header信息(通常可以直接忽略)。

上述解释过于官方,简而言之,chunked编码的基本方法是将大块数据分解成多块小数据,每块都

可以自指定长度,其具体格式如下:

如果为0表明最

后一个块,后面

跟两个结束符

Chunk后有个

结束符

又是一个块

3749字节

结束符

ea5 rn …………………………rn ea5 rn……………………………….rn 0rnrn

其C语言的解码如下,java思路相同

这个块为3749字节,块数

据结束后rn表明这个块

已经结束

这个块为3749字节,块数

据结束后rn表明这个块

已经结束

自己指定长度,

十六进制数ea5

表明这个数据

块有3749字节

int nBytes;

char* pStart = a; // a中存放待解码的数据

char* pTemp;

char strlength[10]; //一个chunk块的长度

chunk : pTemp =strstr(pStart,"rn");

如何将一个十进制数转化为十六进制

char *buf = (char *)malloc(100);

char *d = buf;

int shift = 0;

unsigned long copy = 123445677;

while (copy) {

copy >>= 4;

shift++;

if(NULL==pTemp)

{

free(a);

a=NULL;

}

length=pTemp-pStart;

COPY_STRING(strlength,pStart,length);

pStart=pTemp+2;

nBytes=Hex2Int(strlength); //得到一个块的长度,并转化为十进制

fclose(fp);

return -1;

if(nBytes==0)//如果长度为0表明为最后一个chunk

{

free(a);

fclose(fp);

return 0;

}

fwrite(pStart,sizeof(char),nBytes,fp);//将nBytes长度的数据写入文件中

pStart=pStart+nBytes+2; //跳过一个块的数据以及数据之后两个字节的结束符

fflush(fp);

goto chunk; //goto到chunk继续处理

}//首先计算转化为十六进制后的位数

if (shift == 0)

shift++;

shift <<= 2; //将位数乘于4,如果有两位的话 shift为8

while (shift > 0) {

shift -= 4;

}

*(buf) = hex_chars[(123445677 >> shift) & 0x0F];

buf++;

*buf = '0';

本文标签: 数据长度内容部分发现