理解HTTP协议中的Transfer-Encoding: chunked

2024-01-14 00:32

本文主要是介绍理解HTTP协议中的Transfer-Encoding: chunked,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近写个http客户端的小程序,由于http是基于tcp的无消息边界保护的协议,所以接受时必须要确定接受数据的数量才能完整接收数据。传统的方式,只要先接收到Content-Length就可以通过这个长度接受消息体部分了。而transfer-encoding:chunked的引入,打破了这个规矩,正好找到一篇合适的文章,转载之。
转自: http://hi.baidu.com/ah__fu/blog/item/c3d47b2f0bcd65301e30891e.html
通常,HTTP协议中使用Content-Length这个头来告知数据的长度。然后,在数据下行的过程中,Content-Length的方式要预先在服务器中缓存所有数据,然后所有数据再一股脑儿地发给客户端。
    如果要一边产生数据,一边发给客户端,WEB 服务器就需要使用"Transfer-Encoding: chunked"这样的方式来代替Content-Length。

    "Transfer-Encoding: chunked"是这样编码的:
HTTP头
\r\n
\r\n      --连续的两个\r\n之后就是HTTP体了
16进制值代表的数据长度
\r\n
上面所指的数据长度
\r\n    --每段数据结束后,以\r\n标识

16进制代表的第二段数据
\r\n
XX长度的数据
\r\n

………… (反复通过这样的方式表示每次传输的数据长度)

0      --数据结束部分用0表示,然后是连续的两个\r\n
\r\n
\r\n

      下面的代码演示和如何解析"Transfer-Encoding: chunked"的数据:
//test_chunked.cpp
#include <stdio.h>
#include <string.h>

int Hex2Int(const char* str)
{
    int nResult = 0;
    while (*str!='\0')
    {
        switch (*str)
        {
        case '0'...'9':
            nResult = nResult*16 + *str-'0';
            break;
        case 'a'...'f':
            nResult = nResult*16 + *str-'a'+10;
            break;
        case 'A'...'F':
            nResult = nResult*16 + *str-'A'+10;
            break;
        default:
            return -1;
            break;
        }
        str++;
    }
    return nResult;
}

#define COPY_STRING(dst, src, src_len) do{memcpy((dst), (src), (src_len)); dst[(src_len)]='\0';}while(0);

void test(const char* file)
{
    //
    const int BUFFER_SIZE = 1024*10;
    char* buf = new char[BUFFER_SIZE];
    FILE* fp = fopen(file, "rb");
    if (NULL==fp)
    {
        printf("open file error\n");
        return;
    }
    int nLen = fread(buf, 1, BUFFER_SIZE, fp);
    fclose(fp);
    fp = NULL;
    buf[nLen] = '\0';
    //
    char* pBody = strstr(buf, "\r\n\r\n");
    if (NULL==pBody)
    {
        return;
    }
    pBody += 4;
    FILE* fDst = fopen("result.txt.gz", "ab");
    //下面开始解析
    int nBytes;
    char* pStart = pBody;
    char* pTemp;
    char temp[10];
    do
    {
        pTemp = strchr(pStart, '\r');
        if (NULL==pTemp)
        {
            printf("格式错误!\n");
            break;
        }
        nLen = pTemp-pStart;
        COPY_STRING(temp, pStart, nLen);
        nBytes = Hex2Int(temp);
        pStart = pTemp + 2;
        //下面写入到另一个文件
        if (nBytes>0)
        {
            if (nBytes!=fwrite(pStart, 1, nBytes, fDst))
            {
                printf("write error!\n");
                break;
            }
            pStart += nBytes + 2;
        }
    } while(nBytes>0);
    fclose(fDst);
    fDst = NULL;
    delete[] buf;
    buf = NULL;
}

int main()
{
    test("chunked.txt");
    return 1;
}

这篇关于理解HTTP协议中的Transfer-Encoding: chunked的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/603327

相关文章

HTTP 与 SpringBoot 参数提交与接收协议方式

《HTTP与SpringBoot参数提交与接收协议方式》HTTP参数提交方式包括URL查询、表单、JSON/XML、路径变量、头部、Cookie、GraphQL、WebSocket和SSE,依据... 目录HTTP 协议支持多种参数提交方式,主要取决于请求方法(Method)和内容类型(Content-Ty

Python 基于http.server模块实现简单http服务的代码举例

《Python基于http.server模块实现简单http服务的代码举例》Pythonhttp.server模块通过继承BaseHTTPRequestHandler处理HTTP请求,使用Threa... 目录测试环境代码实现相关介绍模块简介类及相关函数简介参考链接测试环境win11专业版python

使用Python的requests库来发送HTTP请求的操作指南

《使用Python的requests库来发送HTTP请求的操作指南》使用Python的requests库发送HTTP请求是非常简单和直观的,requests库提供了丰富的API,可以发送各种类型的HT... 目录前言1. 安装 requests 库2. 发送 GET 请求3. 发送 POST 请求4. 发送

Go语言使用net/http构建一个RESTful API的示例代码

《Go语言使用net/http构建一个RESTfulAPI的示例代码》Go的标准库net/http提供了构建Web服务所需的强大功能,虽然众多第三方框架(如Gin、Echo)已经封装了很多功能,但... 目录引言一、什么是 RESTful API?二、实战目标:用户信息管理 API三、代码实现1. 用户数据

Python WSGI HTTP服务器Gunicorn使用详解

《PythonWSGIHTTP服务器Gunicorn使用详解》Gunicorn是Python的WSGI服务器,用于部署Flask/Django应用,性能高且稳定,支持多Worker类型与配置,可处... 目录一、什么是 Gunicorn?二、为什么需要Gunicorn?三、安装Gunicorn四、基本使用启

Java对接MQTT协议的完整实现示例代码

《Java对接MQTT协议的完整实现示例代码》MQTT是一个基于客户端-服务器的消息发布/订阅传输协议,MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛,:本文主要介绍Ja... 目录前言前置依赖1. MQTT配置类代码解析1.1 MQTT客户端工厂1.2 MQTT消息订阅适配器1.

深入理解go中interface机制

《深入理解go中interface机制》本文主要介绍了深入理解go中interface机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前言interface使用类型判断总结前言go的interface是一组method的集合,不

Linux中的自定义协议+序列反序列化用法

《Linux中的自定义协议+序列反序列化用法》文章探讨网络程序在应用层的实现,涉及TCP协议的数据传输机制、结构化数据的序列化与反序列化方法,以及通过JSON和自定义协议构建网络计算器的思路,强调分层... 目录一,再次理解协议二,序列化和反序列化三,实现网络计算器3.1 日志文件3.2Socket.hpp

Linux中的HTTPS协议原理分析

《Linux中的HTTPS协议原理分析》文章解释了HTTPS的必要性:HTTP明文传输易被篡改和劫持,HTTPS通过非对称加密协商对称密钥、CA证书认证和混合加密机制,有效防范中间人攻击,保障通信安全... 目录一、什么是加密和解密?二、为什么需要加密?三、常见的加密方式3.1 对称加密3.2非对称加密四、

Java Spring的依赖注入理解及@Autowired用法示例详解

《JavaSpring的依赖注入理解及@Autowired用法示例详解》文章介绍了Spring依赖注入(DI)的概念、三种实现方式(构造器、Setter、字段注入),区分了@Autowired(注入... 目录一、什么是依赖注入(DI)?1. 定义2. 举个例子二、依赖注入的几种方式1. 构造器注入(Con