Boost.Beast中的HTTP分块传输编码详解
beast HTTP and WebSocket built on Boost.Asio in C++11 项目地址: https://gitcode.com/gh_mirrors/be/beast
分块传输编码概述
在HTTP/1.1协议中,当消息体的大小在发送前无法确定时,可以使用分块传输编码(Chunked Transfer Encoding)。这种编码方式将数据分成一系列"块"(chunk),每个块都有自己的大小标识,最后以一个特殊的"最后块"(last chunk)标记结束。
Boost.Beast库提供了完整的支持来处理这种编码方式,既包括自动处理,也包括手动控制的接口,以满足不同场景的需求。
分块传输编码的结构
一个完整的分块传输编码消息包含以下部分:
- 零个或多个分块体(chunked bodies)
- 一个最后块(last chunk)
- 可选的块扩展(chunk-extensions)
- 可选的块尾(trailer)
自动分块处理
Boost.Beast的序列化器(serializer)能够自动应用分块传输编码。当消息的chunked()
方法返回true时,序列化器会自动处理分块逻辑。不过这种方式下:
- 分块边界由实现决定
- 不包含块扩展
- 不包含尾部分块
手动分块控制
对于需要精确控制分块边界、使用块扩展或尾部分块的高级应用场景,Boost.Beast提供了一组辅助类:
核心辅助类
chunk_body
- 表示完整的分块体chunk_crlf
- 表示CRLF分隔符("\r\n"
)chunk_extensions
/basic_chunk_extensions
- 用于构建块扩展的容器chunk_header
- 表示分块头部(包含大小和扩展)chunk_last
- 表示最后块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)能够自动移除分块传输编码,但默认会丢弃块扩展信息。如果需要访问这些信息,可以使用回调接口:
解析回调接口
on_chunk_header
- 在每个分块头部可用时调用- 参数:分块大小、扩展字符串、错误码
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);
实际应用场景
分块传输编码在以下场景特别有用:
- 流式传输大文件或数据
- 实时生成内容(如服务器推送)
- 需要发送元数据(trailer)但无法预先确定内容长度的情况
性能考虑
- 自动分块处理简单但灵活性有限
- 手动分块控制更灵活但需要更多代码
- 回调解析方式可以避免不必要的数据拷贝
总结
Boost.Beast提供了全面而灵活的分块传输编码支持,从简单的自动处理到精细的手动控制,满足不同层次的需求。理解这些接口可以帮助开发者构建更高效的HTTP应用,特别是在处理流式数据或不确定大小的内容时。
beast HTTP and WebSocket built on Boost.Asio in C++11 项目地址: https://gitcode.com/gh_mirrors/be/beast
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考