http chunked编码格式

http的响应数据由下面2部分构成:
响应头 + 数据部分
数据部分的格式由响应头说明
一般情况下,HTTP的响应头包含Content-Length域来指明数据的长度,例如:
有时候,服务器生成HTTP响应时,不好确定响应数据的大小,可能是大文件的下载或后台需要复杂的逻辑处理生成页面,这样一般就使用chunked编码进行传输。使用chunked编码进行传输不用事先说明要传输的页面内容的大小,通过一定的规则指明传输结束。

通常使用chunked编码进行传输的时候,会先将数据进行压缩。HTTP响应头中的Content-Encoding域指明了压缩格式。

http chunked编码格式_第1张图片

当数据很大的时候,还会分多个块(chunk)传输。chunked编码的格式如下:
http chunked编码格式_第2张图片

注意chunk数据长度的单位是字节,不包括后面的\r\n。以一个长度为0的块作为结尾。
把所有的chunk数据部分组合起来存入文件,就是一个标准的gzip压缩文件。

怎么样把所有chunk数据部分提取出来呢?明白了上面的格式,其实就很简单了。
如果我们是通过TCP接收的数据,首先要解决一个问题:找到chunk数据开始的地方,上面提到chunk前面是HTTP响应头。其它先不管,响应头是以连续的\r\n\r\n结尾的,这之后就是响应的数据部分。
假设我们有一个buffer
char *m_contentData;
里面存储着按序收到的所有响应数据。
可以通过如下方式移动到数据部分,即chunked数据开始的地方(下图所示:从A移动到B)

 int n=0;
while(*m_contentData)
{
                 if (*m_contentData=='\r' || *m_contentData=='\n')
                                n++;
                 else
                                n=0;
                 if (n==4)
                                 break;
                m_contentData++;
}
http chunked编码格式_第3张图片

定义char *m_gzipContentData保存gzip数据,可以通过如下方式获取到gzip数据,然后写入文件。

 int len=0;
char ss[10];
char *p = m_contentData;
char *q = m_gzipData;
int gzip_len = 0;
while(1)
{
                sscanf(p, "%s", ss);
                 //read chunk-size
                len = HexToDecimal(ss); //convert hex to decimal
                 if (len == 0) //to chunk end
                                 break;
                p+=2; //read \r\n
                memcpy(q, p, len);
                q += len;
                p += len;
                gzip_len += len;
                p += 2; //read \r\n
}

fwrite(m_gzipData, 1, gzip_len, fp);

你可能感兴趣的:(http chunked编码格式)