Во-первых, вы не можете сделать это:
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))
.Когда вызывается этот обработчик, мы знаем, что операция чтения заканчивается.