我正在实现一个访问 REST 端点的客户端,然后开始处理 SSE stream 并在事件发生时监控它们。为此,我将 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));
}

我的问题是:
  • 对于这个特定用例,这是正确的方法吗?
  • 是否有比 response_parser 更适合用于 responsehttp::string_body 的类型?
  • 当调用 read_event 处理程序时,它如何访问 async_read_some 检索到的内容?它应该从缓冲区中拉出吗?
  • 最佳答案

    我会先回答你的问题,然后再解释。

  • 是的,您想读取 header ,然后调用 read_some(或 read,见下文),直到解析器从 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++ - 使用 boost::beast 异步处理流式 HTTP,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48588627/

    10-11 15:53