boost :: asio async_read гарантирует, что все байты прочитаны - PullRequest
6 голосов
/ 08 февраля 2011

У меня есть сервер, который получает сжатую строку (сжатую с помощью zlib) от клиента, и я использовал async_receive из библиотеки boost::asio для получения этой строки, однако оказывается, что нет никакой гарантии, что все байты будут получены, поэтому я должен изменить его на async_read. Проблема, с которой я сталкиваюсь, заключается в том, что размер получаемых байтов является переменным, поэтому я не уверен, как использовать async_read, не зная количества получаемых байтов. С async_receive у меня просто есть boost::array<char, 1024>, однако это буфер, который не обязательно заполнен полностью.

Я задавался вопросом, может ли кто-нибудь предложить решение, в котором я могу использовать async_read, даже если я не знаю количество байтов, которые должны быть получены заранее?

void tcp_connection::start(boost::shared_ptr<ResolverQueueHandler> queue_handler)
{
    if (!_queue_handler.get())
        _queue_handler = queue_handler;

    std::fill(buff.begin(), buff.end(), 0);

    //socket_.async_receive(boost::asio::buffer(buff), boost::bind(&tcp_connection::handle_read, shared_from_this(), boost::asio::placeholders::error));
    boost::asio::async_read(socket_, boost::asio::buffer(buff), boost::bind(&tcp_connection::handle_read, shared_from_this(), boost::asio::placeholders::error));
}

buff является boost::array<char, 1024>

Ответы [ 3 ]

20 голосов
/ 08 февраля 2011

Как вы ожидали сделать это, используя любой другой метод?

Существует несколько основных способов отправки данных переменного размера в асинхронном поместье:

  1. По сообщению - это означает, что у вас есть заголовок, который определяет длину ожидаемого сообщения, за которым следует тело, которое содержит данные указанной длины.
  2. По потоку - это означает, что у вас есть некоторый маркерный (и это очень широкий) метод определения, когда вы получили полный пакет.
  3. По соединению - каждый полный пакет данных отправляется в одном соединении, которое закрывается после завершения данных.

Так что ваши данные могут быть проанализированы, или длина отправлена ​​и т.д. ...

2 голосов
/ 08 февраля 2011

Используйте async_read_until и создайте собственное условие совпадения или измените протокол для отправки заголовка, включающего количество байтов в сжатой строке.

0 голосов
/ 08 февраля 2011

Один IP-пакет ограничен размером MTU ~ 1500 байт, и все же вы можете загружать файлы размером в гигабайт со своего любимого веб-сайта и смотреть видео размером с мегабайт на YouTube.

Вам необходимо отправить заголовок, указывающий фактический размер необработанных данных, а затем получать данные по частям на более мелкие куски, пока вы не закончите получать все байты.

Например, когда вы загружаете большой файл по HTTP, в заголовке есть поле, указывающее размер файла: Content-Length:.

...