通过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的消息没有问题。另一方面,我的助推::野兽::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来说,这是正确的方法吗?我是否必须向客户端发送一些指示消息确实完成了?使用这种方法,我会遇到超出缓冲区限制的问题吗?

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

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

然后,特别是

callback(data);

这样就完全没有读块的用处了,因为无论如何都会分配相同的内存。相反,您可以提高";"本地配置的极限":

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

默认值为16 miB(自1.75版本起(

旁注

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

最新更新