c++ - 长度未知时如何读取数据?
问题描述
我目前正在使用 boost::asio 跨网络连接读取数据,但选择了一种我认为无效的模式:
auto listener::read(std::function<void(std::error_code ec, packet packet)> callback) noexcept -> void {
m_buffer.resize(1);
m_buffer.shrink_to_fit();
asio::async_read(*m_socket, asio::buffer(m_buffer), asio::transfer_exactly(1),
[&, callback](std::error_code ec, std::size_t length) {
const auto available = m_socket->available();
packet tmp;
tmp.resize(available);
asio::async_read(*m_socket, asio::buffer(tmp), asio::transfer_exactly(available));
tmp.insert(tmp.begin(), std::make_move_iterator(m_buffer.begin()),
std::make_move_iterator(m_buffer.end()));
callback(ec, std::move(tmp));
});
}
(packet
是std::vector<unsigned char>
)
我不确定如何在没有临时的情况下创建它。一开始我无法调整大小m_buffer
,因为我不知道有多少数据即将到来。我尝试m_buffer
仅在 lambda 中使用调整大小来匹配available
+ 1,但我最终丢失了存储在m_buffer
.
当期望一个未知长度的数据包时,有没有更有效的方法来做到这一点?
解决方案
首先,你不能这样做:
asio::async_read(*m_socket, asio::buffer(tmp), asio::transfer_exactly(available)); //[1]
tmp.insert(tmp.begin(), std::make_move_iterator(m_buffer.begin()),
std::make_move_iterator(m_buffer.end())); // [2]
在 [1] 中异步操作开始。async_read
立即返回。然后我们有两个并发操作,第一个插入到tmp
,第二个(异步操作)填充tmp
一些数据。您可以使用同步操作:asio::read
而不是asio::async_read
,前者是阻塞功能,因此insert
仅在读取数据时执行。
如果您不想使用连接向量、创建临时对象等,您可以使用boost::asio::dynamic_buffer:
struct listener {
vector<char> m_buffer;
// others members
};
void listener::read(std::function<void(std::error_code ec, packet p)> callback)
{
boost::asio::async_read(m_socket, boost::asio::dynamic_buffer(m_buffer), boost::asio::transfer_exactly(1),
^^^^^^^^^^^^^
[&, callback](std::error_code ec, std::size_t length)
{
const auto available = m_socket.available();
boost::asio::async_read(m_socket, boost::asio::dynamic_buffer(m_buffer),
^^^^^^^^^^^^^
boost::asio::transfer_exactly(available),
[this,callback](const boost::system::error_code& ec, size_t)
{
callback(ec, std::move(m_buffer));
});
});
}
m_buffer
由异步操作自动增加。你不手动做。如您所见,我添加了新的处理程序 -> where is called callback(ec,move(m_buffer))
。当调用此处理程序时,我们知道读取操作结束。
推荐阅读
- c# - 使用 C# Regex 验证以数字 6 或 7 开头的电话号码
- python - 具有多个绘图的 Bokeh HoverTool
- python - 如何从多个 txt 文件中拆分句子,同时跟踪它来自哪个段落及其在段落中的位置?
- python - 错误:无法为使用 PEP 517 且无法直接安装的熊猫构建轮子
- spring-boot - 在 Spring Boot 中创建 google Oauth2 自定义错误页面
- javascript - 使用机车滚动滚动时图像或内容消失
- react-native - 如何在亚马逊移动分析上进行个人用户跟踪?
- json - 解析 JSON 以角度显示数据
- opencv - 两个版本的 OpenCV 以及如何消除一个
- reactjs - 反应钩子。无法读取嵌套列表的属性“地图”