boost asio async_read: прочитанное сообщение добавляет к себе

Я использую свой компьютер в качестве сервера. Клиент отправляет сообщения типа: «PART1: Part2», а сервер выполняет необходимые действия. Я использую boost asio для кода сервера.

    void start_read()
{
boost::asio::async_read(socket_, input_buffer_,
boost::asio::transfer_at_least(1),
boost::bind(&tcp_connection::handle_read, shared_from_this(),
boost::asio::placeholders::error));
}

// When stream is received handle the message from the client
void handle_read(const boost::system::error_code& error)
{
if (!error)
{
boost::asio::streambuf::const_buffers_type bufs = input_buffer_.data();
std::string msgstr(boost::asio::buffers_begin(bufs),
boost::asio::buffers_begin(bufs) +
input_buffer_.size());

std::vector<std::string> msgVector;
boost::split(msgVector, msgstr, boost::is_any_of(":"));

messageFromClient_ = msgVector[0];
valueFromClient_ = msgVector[1];
};

Сообщения на сервер отправляются каждую секунду, и результирующий msgstr выглядит так:

PART1:part2a
PART1:part2bPART1:part2b
PART1:part2cPART1:part2cPART1:part2c
PART1:part2dPART1:part2dPART1:part2dPART1:part2d

Это не то, что я хочу. Я не хочу включать данные из предыдущего буфера, т.е. я хочу это:

PART1:part2a
PART1:part2b
PART1:part2c
PART1:part2d

Я понимаю, что проблема, скорее всего, заключается здесь:

            std::string msgstr(boost::asio::buffers_begin(bufs),
boost::asio::buffers_begin(bufs) +
input_buffer_.size());

Однако я не могу найти правильный код, который бы работал в моем случае.

РЕДАКТИРОВАТЬ:
Попытался сделать это вместо этого:

std::istream response_istream(&input_buffer_);
std::string msgstr;
response_istream >> msgstr;

Первые три раза я получаю то, что мне нужно, но затем сообщение умножается. Это всегда так:

PART1:part2a
PART1:part2b
PART1:part2c
PART1:part2dPART1:part2d
PART1:part2ePART1:part2e
PART1:part2fPART1:part2fPART1:part2fPART1:part2f
PART1:part2gPART1:part2g

Заранее большое спасибо.

0

Решение

streambuf::data() функция-член возвращает буферы, представляющие входную последовательность. Чтобы избежать повторного доступа к данным, можно использовать streambuf::consume() функция-член для удаления символов из начала входной последовательности. В этом случае, когда данные были скопированы из input_buffer_ в msgstr, последовательность ввода может быть очищена с помощью:

input_buffer_.consume(input_buffer_.size());

Вот полный минимальный пример демонстрирующий поведение consume():

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>

// This example is not interested in the handlers, so provide a noop function
// that will be passed to bind to meet the handler concept requirements.
void noop() {}

int main()
{
using boost::asio::ip::tcp;
boost::asio::io_service io_service;

// Create all I/O objects.
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 0));
tcp::socket server_socket(io_service);
tcp::socket client_socket(io_service);

// Connect client and server sockets.
acceptor.async_accept(server_socket, boost::bind(&noop));
client_socket.async_connect(acceptor.local_endpoint(), boost::bind(&noop));
io_service.run();

// No-consuming case.
{
std::cout << "Non-consuming example" << std::endl;
boost::asio::streambuf streambuf;
for (int i = 0; i < 5; ++i)
{
std::string data = "test";
data += boost::lexical_cast<std::string>(i);

// Write to server.
std::size_t bytes_transferred =
write(client_socket, boost::asio::buffer(data));

// Read from client.
read(server_socket, streambuf,
boost::asio::transfer_exactly(bytes_transferred));

// Print results.
std::string read_data(
boost::asio::buffers_begin(streambuf.data()),
boost::asio::buffers_end(streambuf.data()));
std::cout << "size: " << streambuf.size() << ", "<< "read: " << read_data << std::endl;
}
}

// Consuming case.
{
std::cout << "Consuming example" << std::endl;
boost::asio::streambuf streambuf;
for (int i = 0; i < 5; ++i)
{
std::string data = "test";
data += boost::lexical_cast<std::string>(i);

// Write to server.
std::size_t bytes_transferred =
write(client_socket, boost::asio::buffer(data));

// Read from client.
read(server_socket, streambuf,
boost::asio::transfer_exactly(bytes_transferred));

// Print results.
std::string read_data(
boost::asio::buffers_begin(streambuf.data()),
boost::asio::buffers_end(streambuf.data()));
std::cout << "size: " << streambuf.size() << ", "<< "read: " << read_data << std::endl;

streambuf.consume(bytes_transferred);
}
}
}

И вывод:

Non-consuming example
size: 5, read: test0
size: 10, read: test0test1
size: 15, read: test0test1test2
size: 20, read: test0test1test2test3
size: 25, read: test0test1test2test3test4
Consuming example
size: 5, read: test0
size: 5, read: test1
size: 5, read: test2
size: 5, read: test3
size: 5, read: test4

Обратите внимание, как в случае потребления предыдущие данные отбрасываются.

3

Другие решения


По вопросам рекламы [email protected]