boost::asio::streambuf读写的正确使用方法

问题描述 投票:0回答:1

我有特定格式的数据流,我需要在网络中读/写。目前,我在 boost::asio 中使用

boost::asio::streambuf
和 async_* 函数。有时,我需要尽快读取 ssl 套接字上可用的所有数据,但我不明白如何正确地做到这一点。

现在我正在像这样从 ssl 套接字读取数据:

// m_ssl_stream is ssl socket stream
// m_buffer is a boost::asio::streambuf 
boost::asio::async_read(ssl_stream, m_buffer, boost::asio::transfer_at_least(1), callback);

但是有一个问题。例如,我在 ssl 套接字中有 20.000 个可用字节,但我无法在一次读取操作中读取所有这些数据,因为完成条件

boost::asio::transfer_at_least(1)
通常返回 512 个字节。结果,我在 35-40 次读取操作中读取所有可用数据,而不是 1-2 次。

m_buffer 还用于其他异步操作,可以安排从与其他 async_* 函数相同的数据流中读取。例如,在使用

boost::asio::async_read(ssl_stream, m_buffer, boost::asio::transfer_at_least(1), callback);
读取数据后,如果我的流状态发出信号,我可以使用
boost::beast::http::async_read_header
“去”读取 http 标头。在这种情况下,标头必须出现在
boost::asio::streambuf
中才能在其他异步操作中成功读取标头。

我认为可以使用 m_ssl_stream.async_read_some 操作来完成,但是这个操作不能接受

boost::asio::streambuf
作为缓冲区。

有人知道我该如何实现吗?

c++ asynchronous networking boost boost-asio
1个回答
1
投票

我认为可以使用 m_ssl_stream.async_read_some 操作来完成

我认为相反。事实上,所有组合读取操作(如

asio::async_read
)都是 always 根据一个或多个
s.async_read_some
操作指定的,这实际上是
AsyncReadStream
概念上指定的唯一操作。

你需要做的是明确你的意图。当您期望 20'000 字节时,为什么

transfer_at_least(1)

async_read(ssl_stream, m_buffer, asio::transfer_at_least(1), callback);

可能是

async_read(ssl_stream, m_buffer, asio::transfer_exactly(20'000), callback);

此外,当您不知道有效负载的预期大小(例如

Content-Length
)时,您通常可以使用具有合适条件/模式的
async_read_until

async_read_until(ssl_stream, m_buffer, "\r\n\r\n", callback);

请注意,所有具有动态缓冲区的版本都可能比满足完成条件读取更多。然而,在完成时,

bytes_transferred
反映了满足条件的字节数。因此通常的模式是:

 void callback(error_code ec, size_t bytes_transferred) {
     if (ec.failed()) {
          // handle...
          return;
     }
     
     // use m_buffer...
     m_buffer.consume(bytes_transferred); // keeps remaining buffer content
 }
© www.soinside.com 2019 - 2024. All rights reserved.