Boost Asio read/read_untill некорректная работа

121
09 марта 2021, 02:00

Что то я окончательно запутался, без помощи не могу разобраться: Пытаюсь прочитать ответ от сервера на get запрос, код простой:

boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::resolver::query query(name_URL, "http"); //
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;
tcp::socket socket(io_service);
boost::asio::streambuf request;
std::ostream request_stream(&request);
request_stream << "GET / HTTP/1.1\r\n"
<< "Host: " + name_URL + "\r\n"
<< "Accept: text/html\r\n"
<< "Connection: close\r\n\r\n";
    boost::asio::write(socket, request); //отправляем запрос
    boost::asio::streambuf response;
    boost::asio::read_until(socket, response, "\r\n\r\n"); // Читаем запрос
   // И записываем ответ в текстовый файлик
   std::istream response_stream(&response); // создаем объект потока
   std::string text; // сюда будет считывать из потока getline`ом
    string text_html=""; // Сюда записываем окончательный ответ
    while (!response_stream.eof())
    {
        getline(response_stream, text);
        text_html= text_html + text + "\r\n";
    }
    std::ofstream file("C:\\Response_html.txt");
    file<<text_html;

И теперь позвольте пожалуйста два вопроса: 1)Считывание данных от сервера происходит более, чем не полное, все заголовки приходят 200 ОК и прочая информация, но после заголовков буквально считывается несколько строк и все! Я не понимаю почему! Решил посмотреть, точно ли read_until работает, как надо и заменил

-read_until(socket, response, "\r\n\r\n") на -read_until(socket, response, "200")

То есть я предполагал, что чтение будет ответа будет до 200 ОК, то есть в буффер ответа запишется только HTTP/1.1, но не тут то было, записались минимум все пришедшие заголовки, то есть read_until пропустил указанный для него критерий, читать до "200" и опять таки не понимаю почему :(

2)И позвольте второй вопрос, пытался использовать функцию read за меcто read_until, так теперь кидается исключение: Exeption:read:The end of file. Но почему ?

Answer 1

Во-первых если Вы используете Boost.ASIO, то используйте Boost.Beast для HTTP.

Во-вторых если Вы используете HTTP, то вычитывайте Content-Length байт.

В третьих, while (!response_stream.eof()) это неправильно.

Что касается самого вопроса, то Вы вызываете read_until(socket, response, "\r\n\r\n"); и это заполняет буфер response заголовками + какой-то хвостик данных после "\r\n\r\n". Больше Вы из сокета не читаете, и поэтому в буфере больше ничего нету.

Так что вместо read_until(socket, response, "\r\n\r\n"); читайте сразу до конца потока. И разумеется при это будет ошибка eof.

boost::system::error_code ec;
boost::asio::read(socket, response, boost::asio::transfer_all(), ec);
assert(ec == boost::asio::error::eof);
READ ALSO
Google charts слишком широкие на экране телефона

Google charts слишком широкие на экране телефона

На своем Wordpress-сайте я показываю 2 диаграммы при помощи Google Charts и, к сожалению, на экране мобильных устройств они шире, чем ширина экрана:

132
Реализация INPC для статических свойств

Реализация INPC для статических свойств

Есть класс, содержащий статические переменные, например

99
Как получить из тегов xml-файла значения?

Как получить из тегов xml-файла значения?

Задача — получить из xml-файла все данные из тега offer

113
ошибки Read only asset Packages

ошибки Read only asset Packages

вылезли ошибки, пробовал пере-импортировать пакеты все сразу и по отдельностиУдалось исправить с 76 до 34 ошибок

118