boost::asio::async_read_until не получает полный пакет

Я пытаюсь получить пакет от клиента с помощью boost::asio::async_read_until..

boost::asio::async_read_until(socket, buf, 0x78, boost::bind(&Session::ReadHandler, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));

Клиент отправляет FE 42 54 89 7B 14 05 78 FE 42 55 89 7B 14 05 78 и с помощью async_read_until я получил FE 42 54 89 7B 14 05 78. Теперь, как я могу получить вторую часть пакета? в некоторых случаях клиент объединяет 2 или более пакетов в один перед отправкой на сервер.

Я надеюсь, что это возможно, заранее спасибо!

Изменить 1 мой код

boost::asio::ip::tcp::socket socket;
boost::asio::streambuf buf;

void Session::Read()
{
    boost::asio::async_read_until(socket, buf, 0x78, boost::bind(&Session::ReadHandler, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}

void Session::ReadHandler(const boost::system::error_code &error, std::size_t bytes_transferred)
{
    if (!error)
    {
        boost::asio::streambuf::const_buffers_type data = buf.data();
        std::string packet(boost::asio::buffers_begin(data), boost::asio::buffers_end(data));
        buf.consume(buf.size());
    }
    else
    {
        socket.close();
    }
}

person INIM    schedule 12.07.2014    source источник
comment
Пожалуйста, прочитайте следующую справочную ссылку о том, как задать вопрос таким образом, чтобы люди могли помочь - stackoverflow.com/help/mcve и stackoverflow.com/help/on-topic   -  person Soren    schedule 12.07.2014
comment
поскольку вы упоминаете пакеты, а не потоки данных, ip::udp::socket не соответствует требованиям типа AsyncReadStream, поэтому вы не можете использовать async_read_until.   -  person Sam Miller    schedule 16.07.2014


Ответы (1)


async_read_until делает именно то, что говорит: извлекает данные до тех пор, пока условие не станет истинным, в вашем случае, пока не будет получено 0x78.

Если вы хотите получить больше данных, выполните еще одну операцию async_read_until в том же буфере.

Если вы используете UDP (так что «пакеты» действительно существуют), используйте что-то, что работает с пакетами, например async_receive_from

РЕДАКТИРОВАТЬ: глядя на код (который все еще не является компилируемым примером), он должен, по крайней мере, использовать bytes_transferred как для чтения данных из буфера, так и для использования прочитанного, и ему нужно выполнить еще один async_read_until перед выходом.

person Cubbi    schedule 12.07.2014
comment
Спасибо за ответ, но я все еще не понимаю, как решить проблему.. async_read_until отлично работает, получая FE 42 54 89 7B 14 05 78.. Теперь проблема! Если я выполню еще один async_read_until, он не получит FE 42 55 89 7B 14 05 78, но пропустит этот переход к следующему пакету. Я не знаю реальный размер пакета, потому что он всегда меняется, и я не знаю, в каких случаях клиент добавляет 2 пакета в один. Я использую протокол TCP. - person INIM; 12.07.2014
comment
@INIM Возможно, вы хотите изменить свои пакеты, включив в них флаг, указывающий либо на то, что придет больше, либо на то, что это последний пакет. Затем выполните { read_until } while(packet.flag != LAST); - person u8sand; 12.07.2014
comment
Спасибо, но я думаю, что вы не поняли мою проблему. Это пакет, который клиент отправляет i.imgur .com/Ss2UhZa.png и вот что async_read_until возвращает FF 16 D1 FA 7B 11 12 78 Часть FF 16 D1 0A 7A 12 78 пропускается. Цикл не является проблемой. Проблема в том, что когда я получаю более 1 разделителя, async_read_until возвращает только первую часть.. Есть ли метод для анализа всего пакета? или мне нужно получить байт на байт и проверить его? - person INIM; 12.07.2014
comment
@INIM звучит так, будто нужен полный минимальный пример. По моему опыту, async_read_until ничего не пропускает. - person Cubbi; 12.07.2014
comment
Тогда я не знаю, в чем проблема, потому что сервер продолжает получать пакеты, но (как я уже сказал 3 раза), если в пакете более 1 разделителя, он получает только первую часть. Я добавил свой текущий код в первый Почта.. - person INIM; 12.07.2014
comment
@INIM последуйте совету Кубби, позвоните async_read_until во второй раз. - person Sam Miller; 16.07.2014
comment
@ Сэм Милер, я уже сделал это, но не работает .. - person INIM; 19.07.2014
comment
Одна важная характеристика async_read_until() заключается в том, что она читает до тех пор, пока входные данные не содержат указанного контента — что особенно важно, это означает, что он может читать больше, чем требуемый контент. Таким образом, вам необходимо (а) повторно проверять возвращаемые данные на наличие нескольких последовательностей, которые удовлетворяют вашим требованиям, и (б) сохранять все оставшиеся данные, чтобы добавлять их к последующим прочитанным данным. Подробнее см. этот вопрос. - person Jeremy; 16.01.2017
comment
@Jeremy (b) прав, обновил этот старый ответ, чтобы указать, что буфер должен быть таким же при втором вызове async_read_until - person Cubbi; 16.01.2017