使用 boost::beast 异步处理流式 HTTP
Asynchronous processing of streaming HTTP with boost::beast
我正在实现一个客户端,该客户端访问 REST 端点,然后开始处理 SSE 流并在事件发生时监视事件。 为此,我正在使用 Boost::Beast 版本 124 和 Boost 1.63,并尝试使用async_read_some
以增量方式读取响应正文。
这是我到目前为止的代码:
namespace http = boost::beast::http;
http::response_parser<http::string_body> sse_client::m_parser;
http::response<http::string_body> sse_client::m_response;
boost::beast::flat_buffer m_buffer;
void sse_client::monitor_sse()
{
http::request<http::empty_body> req{http::verb::get, m_target, 11};
req.set(http::field::host, m_host);
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
req.set(http::field::accept, "text/event-stream");
http::async_write(m_socket, req,
std::bind(
&sse_client::process_sse,
shared_from_this(),
std::placeholders::_1,
std::placeholders::_2));
}
void sse_client::process_sse(boost::system::error_code ec, std::size_t byte_count)
{
http::read_header(m_socket, m_buffer, m_parser);
http::async_read_some(m_socket, m_buffer, m_parser,
std::bind(
&sse_client::read_event,
shared_from_this(),
std::placeholders::_1));
}
void sse_client::read_event(boost::system::error_code ec)
{
// TODO: process event
http::async_read_some(m_socket, m_buffer, m_parser,
std::bind(
&sse_client::read_event,
shared_from_this(),
std::placeholders::_1));
}
我的问题是:
- 对于这个特定用例,这是正确的方法吗?
- 有没有比
http::string_body
更适合与response_parser
和response
一起使用的类型? - 调用
read_event
处理程序时,它如何访问async_read_some
检索的内容? 是否应该从缓冲区中提取?
我会先回答你的问题,然后再提供解释。
-
是的,您想读取标头,然后调用 read_some(或读取,见下文),直到解析器从 is_complete() 返回 true。但是,在您的代码中,我注意到您混合了同步和异步调用(read_header后跟 async_read_some)。最好只坚持一个模型,而不是混合它们。
-
出于您的目的,您可能想要buffer_body而不是string_body。文档中有一个示例显示了如何执行此操作 (http://www.boost.org/doc/libs/1_66_0/libs/beast/doc/html/beast/using_http/parser_stream_operations/incremental_read.html)
-
您引用的"缓冲区"是传递给 HTTP 流操作的动态缓冲区参数。虽然此缓冲区将保存消息数据,但应用程序不会对其进行检查。此缓冲区用于保存流算法可以读取的当前消息末尾之后的其他数据(这在 http://www.boost.org/doc/libs/1_66_0/libs/beast/doc/html/beast/using_http/message_stream_operations.html#beast.using_http.message_stream_operations.reading 中进行了说明)。使用buffer_body时,您将通过检查邮件正文来访问内容
http::response_parser::get() 将为您提供对正在读取的消息的访问权限。
最适合您的解决方案是使用示例中的buffer_body,提供一个内存区域来将其指向,然后在循环中调用 read 或 async_read。每次缓冲区已满时,读取将返回错误beast::http::error::need_buffer
,表示需要进一步调用。
希望这有帮助!
- 警告处理为错误这里有什么问题
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 使用流处理接收到的数据
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 基于多个条件处理地图中的所有元素
- 如何用数字处理log(0)
- SSL上的`curl_easy_send`和`curl_asy_recv`:如何处理`CURLE_AGAIN`
- 错误处理.将系统错误代码映射到泛型
- 如何在boost beast http请求中设置http头
- 从文本文件中读取时钟时间和事件时间并进行处理
- 在多个核心中处理一个HTTP请求
- 如果C/C Python3扩展托管HTTP服务器并将Python代码称为请求处理程序,则如何处理并发
- 使用 boost::beast 异步处理流式 HTTP
- 处理HTTP POST请求/响应
- 我可以知道qnetworkAccessManager是否完成了所有HTTP请求的处理
- 如何从 Http 请求处理程序正确终止 POCO 服务器应用程序
- 如何处理HTTP请求