如何使用boost::http::response_parser解析字符串及增量喂入数据
使用boost::http::response_parser实现增量数据解析
我刚好处理过类似的场景,boost::beast的http::response_parser其实天生支持增量喂入数据,只是官方文档更多聚焦在请求解析或者完整数据流的场景,这块的细节没讲清楚。我给你捋清楚具体的实现步骤:
1. 初始化解析器与响应对象
首先要把response_parser和你要填充的response对象绑定起来,这是解析的基础:
#include <boost/beast/http.hpp> namespace http = boost::beast::http; // 定义响应对象(这里用string_body,你可以根据需求换成其他body类型比如file_body) http::response<http::string_body> res; // 初始化解析器并绑定响应对象 http::response_parser<http::string_body> parser; parser.init(res);
2. 增量喂入数据的核心逻辑
解析器的put()方法就是专门用来处理增量数据的,它接受一个const_buffer作为输入,返回一个parser_result结构体,里面包含三个关键信息:
ec:解析过程中的错误码(如果有)bytes_consumed:本次解析处理的字节数is_done()方法:判断是否已经完成整个响应的解析
每次从你的SSLLink获取到数据后,就可以调用put()喂入数据,示例代码如下:
// 假设你的SSLLink获取数据的方法返回一个字节容器,比如std::vector<char> std::vector<char> raw_data = your_ssllink_get_data(); http::const_buffer input_buf(raw_data.data(), raw_data.size()); // 喂入数据并获取解析结果 auto parse_result = parser.put(input_buf); // 首先检查解析错误 if (parse_result.ec) { std::cerr << "解析出错: " << parse_result.ec.message() << std::endl; return; // 或者根据业务逻辑处理错误 } // 检查是否完成整个响应的解析 if (parse_result.is_done()) { // 恭喜!完整的响应已经解析到res对象里了 std::cout << "解析完成,响应状态码: " << res.result_int() << std::endl; std::cout << "响应体内容: " << res.body() << std::endl; // 如果需要继续解析下一个响应,重置解析器 parser.reset(); parser.init(res); } else { // 还需要更多数据,继续从SSLLink获取即可 // 注意:本次未处理的字节会留在input_buf里吗?不——parse_result.bytes_consumed已经标记了已处理的字节数,剩余的字节需要你自己保存,下次喂入时拼接新数据 }
3. 处理未完成的剩余数据
因为每次put()可能只处理部分数据,所以你需要维护一个“剩余缓冲区”来保存未处理完的字节,下次获取新数据后先拼接再喂入。用boost::beast::flat_buffer来做这个缓冲区很方便:
#include <boost/beast/core.hpp> // 定义全局或类成员的剩余缓冲区 boost::beast::flat_buffer leftover_buf; // 每次获取新数据后的处理逻辑 void process_new_data() { std::vector<char> new_data = your_ssllink_get_data(); // 把新数据追加到剩余缓冲区 boost::beast::ostream(leftover_buf) << std::string(new_data.begin(), new_data.end()); // 喂入缓冲区中的数据 auto parse_result = parser.put(leftover_buf.data()); if (parse_result.ec) { std::cerr << "解析出错: " << parse_result.ec.message() << std::endl; return; } // 移除已经处理完成的字节 leftover_buf.consume(parse_result.bytes_consumed); if (parse_result.is_done()) { // 处理完整响应,重置解析器 std::cout << "响应解析完成: " << res << std::endl; parser.reset(); parser.init(res); } }
4. 额外注意事项
- 如果你的响应是分块编码(Transfer-Encoding: chunked),
response_parser会自动处理分块的拼接和解析,直到所有分块都接收完成才会返回is_done()=true,不需要你手动处理分块逻辑。 - 如果你需要解析不同类型的响应体(比如二进制数据),可以把
string_body换成vector_body<char>或者其他适合的body类型。 - 解析器的状态是持续的,只要不调用
reset(),它会一直保留当前的解析进度,直到完成整个响应。
内容的提问来源于stack exchange,提问作者bonacci
相关产品推荐
相关产品推荐

