boost::asio::async_read_until - проблема

Тема в разделе "LANGS.C", создана пользователем _DEN_, 31 окт 2009.

  1. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Читаем заголовок HTTP-запроса (или ответа - не важно). Заголовок оканчивается двумя новыми строками. Соответственно - указываем делимитер:

    boost::asio::async_read_until
    (
    socket,
    streambuf,
    "\r\n\r\n",
    boost::bind(&session::on_header, shared_from_this(), io::placeholders::error)
    );

    *_read_until умеет читать только в streambuf. Соответственно, чтобы потом вынуть данные, на этот streambuf надевается std::istream, и данные вычитываются. Проблема состоит в том, что судя по дебагу *_read_until читает данные блоками (в моем случае - по 512 байт), и ищет делимитер в блоках. То есть после делимитера он скорее всего прочитает еще часть данных. Однако стрим считает, что данных в потоке - ровно до делимитера, не более (то есть в стримбуфе соответствующим образом выставленны границы), хотя в дебаге видно, что данных прочитано больше (то есть размером с блок).

    После прочтения заголовка нужно читать тело, однако, если просто продолжить читать из того же сокета, то тело будет обрезано вначале, как раз на те байты, которые были прочитаны в блок *_read_until после делимитера (думаю, это очевидно).

    Вопрос: как по-человечески разрулить эту ситуацию? Пролождать работать со стримбуфом до конца соединения - не хочется. Хачить стримбуф, выдирать указатели и т.д. - тоже не тру. Нужно какое-то православное решение для вычитывания заголовка через *_read_until с последующим вычитыванием тела через *_receive.
     
  2. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    читай тело и того же потока, в чем проблема-то?
     
  3. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Да, проблема совсем не ясна. Читаешь, читаешь и всего делов.
     
  4. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Так, вернемся к нашим баранам.

    Кое-что прояснилось. Фри-функции asio работают со стримбуфами, мембер-функции сокета работают с asio::buffer (обобщение над массивами и контенерами). Если начать читать фри-функцией, то потом продолжить мембер-функцией не получается.

    Ок, будем все читать и писать фри-функциями. Возникает следующий вопрос, уже не по азио, а по стримам С++:

    Есть streambuf, в нем данные (частично прочитанный HTTP-запрос). На него надевается std::istream и читается пара строк (урл, хедеры, ...). Теперь мне нужно как-то заресетить стрим, или стримбуф. То есть чтобы если я снова начал читать из этого стрима, то чтение началось сначала. Как это сделать?
     
  5. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    pubsetbuf?
     
  6. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    clear()?
     
  7. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    В общем так. У asio::streambuf можно спросить data(), которая в свою очередь может быть проитерирована через asio::buffers_begin / buffers_end - вот и вся любовь.
     
  8. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Изврат какой-то, в стримбуфер лезть из апликухи.
     
  9. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Booster

    В примерах делается именно так. К тому же, ::data() это функция boost::asio::basic_streambuf, а не STL-ного предка. По-видимому введена в streambuf именно с целью доступа к данным.
     
  10. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Если так, то это плохо. Торчать наружу потоковый накопитель(буфер), не должен. Если не хватает функциональности istream, то его можно доработать, как например сделано с ifstream. А streambuf это низкоуровневая вещь.
     
  11. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Нельзя сказать, что доступ пользователя к стримбуфу - это всегда плохо. Если бы это было сугубо библиотечный класс, то он был бы наверно в чьей-либо private-секции, или не имел бы публичного интерфейса.

    А раз он имеет публичные методы, то наверно это потому, что пользователю все же иногда может потребоваться их вызывать.
     
  12. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Да rdbuf в паблик секции, но без особой нужды я бы к нему не прибегал, лучше istream заточить.