长度未知时如何读取数据?

时间:2019-02-06 12:58:00

标签: c++ c++11 boost-asio

我目前正在使用boost :: asio跨网络连接读取数据,但是我认为这种模式无效:

NSCache

({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>的大小,因为我不知道会有多少数据。我试图只在lambda中使用m_buffer来调整大小以匹配m_buffer + 1,但是我最终丢失了存储在available中的第一个字节。

当期望未知长度的数据包时,有没有更有效的方法?

1 个答案:

答案 0 :(得分:1)

首先,您不能这样做:

 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通过异步操作自动增加。您无需手动操作。如您所见,我添加了新的处理程序->,其位置为callback(ec,move(m_buffer))。调用此处理程序后,我们知道读取操作将结束。