【问题标题】:Receiving large binary data over Boost::Beast websocket通过 Boost::Beast websocket 接收大型二进制数据
【发布时间】:2021-07-10 20:32:18
【问题描述】:

我正在尝试使用 boost::beast::websocket 接收大量数据,该数据由另一个 boost::beast::websocket 提供。通常,这些数据会发送到连接的浏览器,但我想设置一个纯 C++ 单元测试来验证流量的某些组件。我将发送方的自动分段设置为 true,最大大小为 1MB,但在发送几条消息后,接收方会吐出:

Read 258028 bytes of binary
Read 1547176 bytes of binary
Read 168188 bytes of binary
"Failed read: The WebSocket message exceeded the locally configured limit"

现在,我不应该期望一个完全开发且支持良好的浏览器会表现出与我可能架构不佳的单元测试相同的特征,但事实并非如此。浏览器通过 websocket 读取 25MB 消息没有问题。另一方面,我的 boost::beast::websocket 达到了极限。

所以在我陷入困境之前,我想看看是否有人对此有任何想法。我的阅读部分如下所示:

void on_read(boost::system::error_code ec, std::size_t bytes_transferred)
{
    boost::ignore_unused(bytes_transferred);

    if (ec)
    {
        m_log.error("Failed read: " + ec.message());
        // Stop the websocket
        stop();
        return;
    }

    std::string data(boost::beast::buffers_to_string(m_buffer.data()));

    // Yes I know this looks dangerous. The sender always sends as binary but occasionally sends JSON 
    if (data.at(0) == '{')
        m_log.debug("Got message: " + data);
    else
        m_log.debug("Read " + utility::to_string(m_buffer.data().buffer_bytes()) + " of binary data");

    // Do the things with the incoming doata
    for (auto&& callback : m_read_callbacks)
        callback(data);

    // Toss the data
    m_buffer.consume(bytes_transferred);

    // Wait for some more data
    m_websocket.async_read(
        m_buffer,
        std::bind(
            &WebsocketClient::on_read,
            shared_from_this(),
            std::placeholders::_1,
            std::placeholders::_2));
}

我在一个单独的示例中看到,您可以执行 for/while 循环读取一些数据,直到消息完成 (https://www.boost.org/doc/libs/1_67_0/libs/beast/doc/html/beast/using_websocket/send_and_receive_messages.html),而不是执行异步读取。对于可以发送一些相当大量消息的始终打开的 websocket,这是否是正确的方法?我是否必须向客户端发送一些指示消息确实已完成?使用这种方法会遇到超出缓冲区限制的问题吗?

【问题讨论】:

    标签: c++ boost websocket boost-beast


    【解决方案1】:

    如果你的使用模式是固定的:

    std::string data(boost::beast::buffers_to_string(m_buffer.data()));
    

    然后,特别是

        callback(data);
    

    那么按块读取将毫无用处,因为无论如何您都将分配相同的内存。相反,你可以raise the "locally configured limit":

    ws.read_message_max(20ull << 20); // sets the limit to 20 miB
    

    默认值为 16 miB(自 boost 1.75 起)。

    旁注

    您还可以使用ws.got_binary() 来检测收到的最后一条消息是否是二进制的。

    【讨论】:

    • 这始终是您忽略的一个选项...谢谢。
    猜你喜欢
    • 1970-01-01
    • 2018-10-06
    • 1970-01-01
    • 2019-06-02
    • 1970-01-01
    • 2018-11-28
    • 1970-01-01
    • 1970-01-01
    • 2014-03-16
    相关资源
    最近更新 更多