Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: wxHTTP - отображение html содержимого
Форум на CrossPlatform.RU > Библиотеки > wxWidgets
wxFan
Привет всем! Проблема заключается в отображении содержимого страницы с инета на консоль. Запрос успешно проходит, но вот попытка распаковать содержимое и впихать его в wxString приводит к переполнению wxString объекта. Без отладки это выглядит как пустая консолька, которая через некоторое время валится с ошибкой SIGSEGV. Валится прога после вызова Read. Сам вызов при отлаживании около 5сек происходит (курсор текущей строки отладки пропадает, после чего появляется вместе с SIGSEGV ошибкой на следующей после ...Read строки)
Функция, занимающаяся коннектом
#include заголовок
wxString MyClass::GetPageContent()
{
    wxHTTP *con = new wxHTTP();
    con->SetHeader("User-Agent", юзер агент);
    con->SetHeader("Host", хост);
    con->SetHeader("Accept", "text/html");
    con->SetHeader("Accept-Language", "ru-RU,ru;q=0.9,en;q=0.8");
    con->SetHeader("Accept-Encoding", "gzip, deflate");
              con->SetHeader("Connection", "Keep-Alive");
    con->Connect(хост);
    
    //wxFileOutputStream fileStream("C:\\1.gzip");
    //fileStream.Write(*(con->GetInputStream("/")));
    //fileStream.Close();

    wxByte buf[30000];
    wxZlibInputStream inStream(con->GetInputStream("/"), wxZLIB_GZIP);
    inStream.Read(buf, 30000);
    wxString resp(buf);
    con->GetResponse();
    
    wxDELETE(con);
    return resp;
}


Консолька
#include "App.h"
bool MyApp::OnInit()
{
    MyClass *client = new MyClass();
    wxPuts(client->GetPageContent());
    return true;
}


Если убрать код, занимающийся распаковкой gzip и записью распакованного содержимого в буфер, а взамен раскомментировать 3 строчки, то на хард успешно запишется файл 1.gzip (5кб), распаковав который архиватором получается файл без расширения (11кб), который содержит в себе нужную страницу. Несмотря на это запись файла в 5кб происходит подозрительно небыстро (может, около 5 сек +-): почти мгновенно появляется файл в 4кб и уже под конец еще кб добавляется и консолька завершает свою работу.
MinGW, Win7 Sp1 Pro, CodeLite IDE 3.0.5045, wxWidgets 2.9.2 (unicode=on)
Iron Bug
тут возможны тонкости с кодировкой. почему бы не использовать wxChar вместо wxByte? он, по крайней мере, не будет зависеть от настроек компиляции проекта.
я вот даже навскидку не могу сказать, к чему он приведёт wxByte в конструкторе wxString и как он будет вычислять длину, которая в этом конструкторе не указана явно. а неявно там применяются методы преобразования строк, расписанные в документации на wxString и соответственно, разные методы вычисления длины строки. скорее всего, его заглючивает в этом месте и он не может преобразовать строки.
я думаю, всё это отлично можно поглядеть в дебаге или хотя бы проверить длину полученной строки.
wxFan
Сменил код на следующий, тоже самое. Вероятно, какой-либо баг, либо я по-прежнему что-то упускаю.

Code
wxString SomeFunc()
{
    wxHTTP *con = new wxHTTP();
    con->SetHeader("User-Agent", "Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.9.168 Version/11.51");
    con->SetHeader("Host", "some url");
    con->SetHeader("Accept", "text/html");
    con->SetHeader("Accept-Language", "ru-RU,ru;q=0.9,en;q=0.8");
    con->SetHeader("Accept-Encoding", "gzip, deflate");
              con->SetHeader("Connection", "Keep-Alive");
    wxZlibInputStream inStream(con->GetInputStream("/"), wxZLIB_GZIP);
    wxTextInputStream txtStream(inStream);
    wxString resp = txtStream.ReadWord();
    
    wxDELETE(con);
    return resp;
}

Успешно проходит запрос, после чего получаю ошибку, как можно увидеть на скриншоте ниже на функции OnSysRead:

Функция OnSysRead:
size_t wxZlibInputStream::OnSysRead(void *buffer, size_t size)
{
  wxASSERT_MSG(m_inflate && m_z_buffer, wxT("Inflate stream not open"));

  if (!m_inflate || !m_z_buffer)
    m_lasterror = wxSTREAM_READ_ERROR;
  if (!IsOk() || !size)
    return 0;

  int err = Z_OK;
  m_inflate->next_out = (unsigned char *)buffer;
  m_inflate->avail_out = size;

  while (err == Z_OK && m_inflate->avail_out > 0) {
    if (m_inflate->avail_in == 0 && m_parent_i_stream->IsOk()) {
      m_parent_i_stream->Read(m_z_buffer, m_z_size);
      m_inflate->next_in = m_z_buffer;
      m_inflate->avail_in = m_parent_i_stream->LastRead();
    }
    err = inflate(m_inflate, Z_SYNC_FLUSH);
  }

  switch (err) {
    case Z_OK:
        break;

    case Z_STREAM_END:
      if (m_inflate->avail_out) {
        // Unread any data taken from past the end of the deflate stream, so that
        // any additional data can be read from the underlying stream (the crc
        // in a gzip for example)
        if (m_inflate->avail_in) {
          m_parent_i_stream->Reset();
          m_parent_i_stream->Ungetch(m_inflate->next_in, m_inflate->avail_in);
          m_inflate->avail_in = 0;
        }
        m_lasterror = wxSTREAM_EOF;
      }
      break;

    case Z_BUF_ERROR:
      // Indicates that zlib was expecting more data, but the parent stream
      // has none. Other than Eof the error will have been already reported
      // by the parent strean,
      m_lasterror = wxSTREAM_READ_ERROR;
      if (m_parent_i_stream->Eof())
      {
          wxLogError(_("Can't read inflate stream: unexpected EOF in underlying stream."));
      }
      break;

    default:
      wxString msg(m_inflate->msg, *wxConvCurrent);
      if (!msg)
        msg = wxString::Format(_("zlib error %d"), err);
      wxLogError(_("Can't read from inflate stream: %s"), msg.c_str());
      m_lasterror = wxSTREAM_READ_ERROR;
  }

  size -= m_inflate->avail_out;
  m_pos += size;
  return size;
}
Sokoloff
Может вам поиграться с заголовком "Accept-Encoding"? Или сменить метод, или даже отключить сжатие совсем.
Iron Bug
с wxWiki по wxHTTP:
Цитата
wxInputStream *GetInputStream(const wxString& path)
Get a page from the server specified by the last call to Connect(...). Path is path to a resource on the server not a full URL.
Note: You must call one of the Connect functions at least once before using this function or the result will be NULL.

Внимательно читаем документацию
wxFan
Доки читал, оказалось по енвнимательности забыл этот коннект. Всем спасибо, проблема решена)))
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2020 IPS, Inc.