Boost.Beast中的HTTP分块传输编码详解

Boost.Beast中的HTTP分块传输编码详解

beast HTTP and WebSocket built on Boost.Asio in C++11 beast 项目地址: https://gitcode.com/gh_mirrors/be/beast

分块传输编码概述

在HTTP/1.1协议中,当消息体的大小在发送前无法确定时,可以使用分块传输编码(Chunked Transfer Encoding)。这种编码方式将数据分成一系列"块"(chunk),每个块都有自己的大小标识,最后以一个特殊的"最后块"(last chunk)标记结束。

Boost.Beast库提供了完整的支持来处理这种编码方式,既包括自动处理,也包括手动控制的接口,以满足不同场景的需求。

分块传输编码的结构

一个完整的分块传输编码消息包含以下部分:

  1. 零个或多个分块体(chunked bodies)
  2. 一个最后块(last chunk)
  3. 可选的块扩展(chunk-extensions)
  4. 可选的块尾(trailer)

自动分块处理

Boost.Beast的序列化器(serializer)能够自动应用分块传输编码。当消息的chunked()方法返回true时,序列化器会自动处理分块逻辑。不过这种方式下:

  • 分块边界由实现决定
  • 不包含块扩展
  • 不包含尾部分块

手动分块控制

对于需要精确控制分块边界、使用块扩展或尾部分块的高级应用场景,Boost.Beast提供了一组辅助类:

核心辅助类

  1. chunk_body - 表示完整的分块体
  2. chunk_crlf - 表示CRLF分隔符("\r\n")
  3. chunk_extensions/basic_chunk_extensions - 用于构建块扩展的容器
  4. chunk_header - 表示分块头部(包含大小和扩展)
  5. chunk_last - 表示最后块
  6. make_chunk/make_chunk_last - 用于构造分块的辅助函数

使用示例

基本分块发送
// 先发送消息头
response<string_body> res{status::ok, 11};
res.set(field::server, "Beast");
res.set(field::transfer_encoding, "chunked");
write(sock, res.base());

// 然后手动发送分块
write(sock, make_chunk(buffer("First")));
write(sock, make_chunk(buffer("Hello, world!")));
write(sock, make_chunk_last());
带扩展的分块
chunk_extensions exts;
exts.insert("quality", "1.0");
write(sock, make_chunk(buffer("Hello"), exts));
带尾部分块
fields trailers;
trailers.set(field::expires, "never");
trailers.set("Content-MD5", "f4a5c16584f03d90");
write(sock, make_chunk_last(trailers));

分块解析处理

Boost.Beast的解析器(parser)能够自动移除分块传输编码,但默认会丢弃块扩展信息。如果需要访问这些信息,可以使用回调接口:

解析回调接口

  1. on_chunk_header - 在每个分块头部可用时调用
    • 参数:分块大小、扩展字符串、错误码
  2. on_chunk_body - 在分块体数据可用时调用
    • 参数:剩余字节数、数据缓冲区、错误码

解析示例

parser<string_body> p;
p.on_chunk_header([](uint64_t size, string_view extensions, error_code& ec) {
    if(size == 0)
        cout << "Last chunk\n";
    else
        cout << "Chunk size: " << size << "\n";
    
    // 解析扩展
    chunk_extensions exts;
    exts.parse(extensions);
    for(auto const& ext : exts)
        cout << "Extension: " << ext.first << " = " << ext.second << "\n";
});

p.on_chunk_body([](uint64_t remain, string_view body, error_code& ec) {
    cout << "Chunk data: " << body << "\n";
    return body.size(); // 消费所有数据
});

// 读取并处理消息
read(sock, buffer, p);

实际应用场景

分块传输编码在以下场景特别有用:

  1. 流式传输大文件或数据
  2. 实时生成内容(如服务器推送)
  3. 需要发送元数据(trailer)但无法预先确定内容长度的情况

性能考虑

  1. 自动分块处理简单但灵活性有限
  2. 手动分块控制更灵活但需要更多代码
  3. 回调解析方式可以避免不必要的数据拷贝

总结

Boost.Beast提供了全面而灵活的分块传输编码支持,从简单的自动处理到精细的手动控制,满足不同层次的需求。理解这些接口可以帮助开发者构建更高效的HTTP应用,特别是在处理流式数据或不确定大小的内容时。

beast HTTP and WebSocket built on Boost.Asio in C++11 beast 项目地址: https://gitcode.com/gh_mirrors/be/beast

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

施刚爽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值