Обработка HTTP response, срочно нужна помощь
От: Аноним  
Дата: 14.05.08 04:39
Оценка: :)
Есть задача дизайна, уже всю голову сломал какую реализацию выбрать
Итак, написан код для отправки HTTP GET и POST сообщений используя следующее API из WinInet.lib: InternetOpen(), InternetConnect(), HttpOpenRequest(), HttpAddRequestHeaders(), HttpSendRequest(). Запросы уходят отлично, проблемы с чтением приемов. В ответе я ожидаю получить HTML страничку, а затем парсить ее.
Теперь начинаются вопросы:
1 — При вызове HttpQueryInfo() с параметром HTTP_QUERY_CONTENT_LENGTH возвращается ERROR_HTTP_HEADER_NOT_FOUND. Это нормально в случае, если я ожидаю получить в ответе HTML страницу?
2 — Т.к. нет возможности узнать размер контента, то наверное можно попытаться читать данные в цикле с помощью InternetQueryDataAvailable() и InternetReadFile(). Теперь нужно как-то сохранить данные, и вот тут начинаются сложности. Т.к. размера данных мы не знаем до тех самых пор, пока не дочитаем до конца, то сразу аллокировать память нужного размера не получится. Насколько это корректно перенаправлять данные в файл, а затем уже парсить его? Софт будет крутиться на Windows Mobile. Можно, конечно, выделить большой буфер, и в случае, если размер конента превышает его, то просто проигнорировать остаток данных, но это как-то криво выглядит. Вот такая дилема Какие еще варианты посоветуете?

Задача исключительно важная и срочная.

Заранее спасибо!

14.05.08 15:50: Перенесено модератором из 'C/C++' — Кодт
wininet windows mobile
Re: Обработка HTTP response, срочно нужна помощь
От: c-smile Канада http://terrainformatica.com
Дата: 14.05.08 06:00
Оценка:
Здравствуйте, Аноним, Вы писали:


А>2 — Т.к. нет возможности узнать размер контента, то наверное можно попытаться читать данные в цикле с помощью InternetQueryDataAvailable() и InternetReadFile(). Теперь нужно как-то сохранить данные, и вот тут начинаются сложности. Т.к. размера данных мы не знаем до тех самых пор, пока не дочитаем до конца, то сразу аллокировать память нужного размера не получится. Насколько это корректно перенаправлять данные в файл, а затем уже парсить его? Софт будет крутиться на Windows Mobile. Можно, конечно, выделить большой буфер, и в случае, если размер конента превышает его, то просто проигнорировать остаток данных, но это как-то криво выглядит. Вот такая дилема Какие еще варианты посоветуете?


Код препологает что вопрошающий знаком с понятием динамический массив:

#define BUFLEN 4096
byte buf[BUFLEN];
array<byte> data;

while(data.size() < 32*1024*1024)
{
  DWORD dwBytesRead = 0;
  BOOL r = InternetReadFile( hRequest, buf, BUFLEN, &dwBytesRead);
  if(!r || !dwBytesRead) 
        break;
  data.push(buff,dwBytesRead);
}
Re[2]: Обработка HTTP response, срочно нужна помощь
От: Аноним  
Дата: 14.05.08 06:35
Оценка:
К сожалению нет динамических массивов в WM, да и stl они туда не притащили.
Re: Обработка HTTP response, срочно нужна помощь
От: Were  
Дата: 14.05.08 07:53
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть задача дизайна, уже всю голову сломал какую реализацию выбрать

А>Итак, написан код для отправки HTTP GET и POST сообщений используя следующее API из WinInet.lib: InternetOpen(), InternetConnect(), HttpOpenRequest(), HttpAddRequestHeaders(), HttpSendRequest(). Запросы уходят отлично, проблемы с чтением приемов. В ответе я ожидаю получить HTML страничку, а затем парсить ее.
А>Теперь начинаются вопросы:
А>1 — При вызове HttpQueryInfo() с параметром HTTP_QUERY_CONTENT_LENGTH возвращается ERROR_HTTP_HEADER_NOT_FOUND. Это нормально в случае, если я ожидаю получить в ответе HTML страницу?
А>2 — Т.к. нет возможности узнать размер контента, то наверное можно попытаться читать данные в цикле с помощью InternetQueryDataAvailable() и InternetReadFile(). Теперь нужно как-то сохранить данные, и вот тут начинаются сложности. Т.к. размера данных мы не знаем до тех самых пор, пока не дочитаем до конца, то сразу аллокировать память нужного размера не получится. Насколько это корректно перенаправлять данные в файл, а затем уже парсить его? Софт будет крутиться на Windows Mobile. Можно, конечно, выделить большой буфер, и в случае, если размер конента превышает его, то просто проигнорировать остаток данных, но это как-то криво выглядит. Вот такая дилема Какие еще варианты посоветуете?

А>Задача исключительно важная и срочная.


А>Заранее спасибо!


1. Думаю да.
2. Ну допустим HeapAlloc/HeapReAlloc/HeapFree есть на "Windows Mobile Version 5.0 and later".
Re: Обработка HTTP response, срочно нужна помощь
От: The Lex Украина  
Дата: 14.05.08 08:50
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Теперь начинаются вопросы:

А>1 — При вызове HttpQueryInfo() с параметром HTTP_QUERY_CONTENT_LENGTH возвращается ERROR_HTTP_HEADER_NOT_FOUND. Это нормально в случае, если я ожидаю получить в ответе HTML страницу?

имхо, ты просто не дождался еще ответа в этот момент. как вариант, ты получил РЕЕЗ-ответ "безразмерный" — не содержащий в своем заголовке своей длины вообще: тогда да, читаешь кусками (размер куска выбираешь от задачи), пишешь парсер "кусочный" — который предполагает, что данные ему будут кусками даваться и в случае необходимости он может потребовать от "условного читающего" следующий кусок — и парсишь. Есть точно только HTML-страницы — можно считать концом тег </HTML>.

MSDN также дает пример использования пары InternetQueryDataAvailable() + InternetReadFile() для вычитки "всего что вообще удалось получить" — тоже вариант, просто плотнее упирается на реализацию WinInet, имхо.
Голь на выдумку хитра, однако...
Re[3]: Обработка HTTP response, срочно нужна помощь
От: Кодт Россия  
Дата: 14.05.08 12:01
Оценка: +1
Здравствуйте, <Аноним>, Вы писали:

А>К сожалению нет динамических массивов в WM, да и stl они туда не притащили.


В винмобайле нет STL?!! Поищи-ка повнимательнее.
И кстати, ATL с его контейнерами там тоже следует поискать.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[4]: Обработка HTTP response, срочно нужна помощь
От: Аноним  
Дата: 14.05.08 14:28
Оценка:
ATL есть, а STL точно нет. Пока больше склоняюсь к realloc-у. Хотя вариант записи в файл так же не исключаю
Re[5]: Обработка HTTP response, срочно нужна помощь
От: c-smile Канада http://terrainformatica.com
Дата: 14.05.08 17:38
Оценка:
Здравствуйте, Аноним, Вы писали:

А>ATL есть, а STL точно нет. Пока больше склоняюсь к realloc-у. Хотя вариант записи в файл так же не исключаю



/**pod namespace - POD primitives. **/
namespace pod
{
  template <typename T> void copy ( T* dst, const T* src, size_t nelements)
  {
      memcpy(dst,src,nelements*sizeof(T));
  }
  template <typename T> void move ( T* dst, const T* src, size_t nelements)
  {
      memmove(dst,src,nelements*sizeof(T));
  }

  /** buffer  - in-memory dynamic buffer implementation. **/
  template <typename T>
    class buffer 
    {
      T*              _body;
      size_t          _allocated;
      size_t          _size;

      T*  reserve(size_t size)
      {
        size_t newsize = _size + size;
        if( newsize > _allocated ) 
        {
          _allocated = (_allocated * 3) / 2;
          if(_allocated < newsize) _allocated = newsize;
          T *newbody = new T[_allocated];
          copy(newbody,_body,_size);
          delete[] _body;
          _body = newbody;
        }
        return _body + _size;
      }

    public:

      buffer():_size(0)        { _body = new T[_allocated = 256]; }
      ~buffer()                { delete[] _body;  }

      const T * data()   
      {  
               if(_size == _allocated) reserve(1); 
               _body[_size] = 0; return _body; 
      }

      size_t length() const         { return _size; }

      void push(T c)                { *reserve(1) = c; ++_size; }
      void push(const T *pc, size_t sz) { copy(reserve(sz),pc,sz); _size += sz; }

      void clear()                  { _size = 0; }

    };

    typedef buffer<byte> byte_buffer; 
    typedef buffer<wchar_t> wchar_buffer; 
    typedef buffer<char> char_buffer; 
}


В моем примере подставь


pod::byte_buffer bytes_received;
...
bytes_received.push( buf, n_bytes_in_buf );

bytes_received.data();
bytes_received.length();



А html ты как/чем собрался прасить-то?
Re[2]: Обработка HTTP response, срочно нужна помощь
От: c-smile Канада http://terrainformatica.com
Дата: 14.05.08 21:28
Оценка: :))
Здравствуйте, The Lex, Вы писали:


TL>... Есть точно только HTML-страницы — можно считать концом тег </HTML>.


Tags <html> and </html> are optional in HTML.

От засада, да?
Re[3]: Обработка HTTP response, срочно нужна помощь
От: The Lex Украина  
Дата: 15.05.08 16:56
Оценка:
Здравствуйте, c-smile, Вы писали:

TL>>... Есть точно только HTML-страницы — можно считать концом тег </HTML>.

CS>Tags <html> and </html> are optional in HTML.
CS>От засада, да?

Да, засада. Какие есть предложения как ловить конец файла?
Голь на выдумку хитра, однако...
Re[4]: Обработка HTTP response, срочно нужна помощь
От: c-smile Канада http://terrainformatica.com
Дата: 15.05.08 21:05
Оценка:
Здравствуйте, The Lex, Вы писали:

TL>Да, засада. Какие есть предложения как ловить конец файла?


BOOL r = InternetReadFile( hRequest, buf, BUFLEN, &dwBytesRead);
if(!r || !dwBytesRead) 
     break;
Re: Обработка HTTP response, срочно нужна помощь
От: djs_ Россия  
Дата: 19.05.08 05:17
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть задача дизайна, уже всю голову сломал какую реализацию выбрать

А>Итак, написан код для отправки HTTP GET и POST сообщений используя следующее API из WinInet.lib: InternetOpen(), InternetConnect(), HttpOpenRequest(), HttpAddRequestHeaders(), HttpSendRequest(). Запросы уходят отлично, проблемы с чтением приемов. В ответе я ожидаю получить HTML страничку, а затем парсить ее.
А>Теперь начинаются вопросы:
А>1 — При вызове HttpQueryInfo() с параметром HTTP_QUERY_CONTENT_LENGTH возвращается ERROR_HTTP_HEADER_NOT_FOUND. Это нормально в случае, если я ожидаю получить в ответе HTML страницу?
А>2 — Т.к. нет возможности узнать размер контента, то наверное можно попытаться читать данные в цикле с помощью InternetQueryDataAvailable() и InternetReadFile(). Теперь нужно как-то сохранить данные, и вот тут начинаются сложности. Т.к. размера данных мы не знаем до тех самых пор, пока не дочитаем до конца, то сразу аллокировать память нужного размера не получится. Насколько это корректно перенаправлять данные в файл, а затем уже парсить его? Софт будет крутиться на Windows Mobile. Можно, конечно, выделить большой буфер, и в случае, если размер конента превышает его, то просто проигнорировать остаток данных, но это как-то криво выглядит. Вот такая дилема Какие еще варианты посоветуете?

Если HTTP >= 1.1, то если нет Content-Length, то перед каждым блоком будет строка с кол-вом байт в очередном блоке (и заголовок Content-encoding: chunked).
Если HTTP < 1.1, то можно читать данные любыми удобными порциями, пока сервер не закроет соединение.
--
Спасибо
Re[6]: Обработка HTTP response, срочно нужна помощь
От: Argo1978 США  
Дата: 21.05.08 21:02
Оценка:
Автором темы был я.

Спасибо,
т.к. изначально предполагал парсинг с помощью IXMLDOM, то решил не исользовать динамический массив, а ограничиться HeapReAlloc.

do
{
dwNumberOfBytesAvailable = 0;
if(InternetQueryDataAvailable( m_hHttpRequest
,&dwNumberOfBytesAvailable
,NULL
,NULL))
{
RETAILMSG(1, (TEXT("InternetQueryDataAvailable() return %d bytes available\n"), dwNumberOfBytesAvailable));
if(dwNumberOfBytesAvailable == 0)
{
bDone = TRUE;
dwResult = ERROR_SUCCESS;
}
else
{
PBYTE pNewBlockOfData = NULL;
if(pData == NULL)
{
pNewBlockOfData = (PBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwNumberOfBytesAvailable + 1);
dwBytesAllocated += dwNumberOfBytesAvailable + 1;
}
else
{
pNewBlockOfData = (PBYTE)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pData, dwBytesAllocated + dwNumberOfBytesAvailable);
dwBytesAllocated += dwNumberOfBytesAvailable;
}

if(pNewBlockOfData != NULL)
{
pData = pNewBlockOfData;
dwNumberOfBytesRemaining = dwNumberOfBytesAvailable;
do
{
if(InternetReadFile( m_hHttpRequest
,(LPVOID)(pData + dwNumberOfBytesRetrieved)
,dwNumberOfBytesRemaining
,&dwNumberOfBytesReturned))
{
dwNumberOfBytesRemaining -= dwNumberOfBytesReturned;
dwNumberOfBytesRetrieved += dwNumberOfBytesReturned;
}
else
{
bDone = TRUE;
dwNumberOfBytesRemaining = 0;
dwResult = GetLastError();
RETAILMSG(1, (TEXT("InternetReadFile() error = %d \n"), dwResult));
}
}
while(dwNumberOfBytesRemaining > 0);
}
else
{
bDone = TRUE;
RETAILMSG(1, (TEXT("ReadHttpContent(): failed to allocate %d bytes \n"), dwNumberOfBytesAvailable));
dwResult = ERROR_NOT_ENOUGH_MEMORY;
}
}
}
else
{
bDone = TRUE;
dwResult = GetLastError();
RETAILMSG(1, (TEXT("InternetQueryDataAvailable() error = %d \n"), dwResult));
}
}
while(!bDone);

На всякий случай сразу реализовал и вывод в файл.
Вот теперь стою перед дилеммой как парсить HTML & XML. Впринципе, парсинг XML достаточно тривиален. Решил пойти стандартным путем, написал утилитный класс для использования IXMLDOM и сам парсер для сообщений, представленных в виде XML. А вот извлечения XML из HTML оставил на последок. Сначала решил посмотреть что люди пишут по этому поводу и набрел на знакомый ник http://www.codeproject.com/KB/recipes/HTML_XML_Scanner.aspx
Вообщем спасибо большое, все так стройненько и аккуратненько. Руки чешутся прикрутить поскорее
Re[2]: Обработка HTTP response, срочно нужна помощь
От: pjBrain  
Дата: 23.05.08 08:24
Оценка:
Здравствуйте, The Lex, Вы писали:

TL>Здравствуйте, Аноним, Вы писали:


TL>... пишешь парсер "кусочный" — который предполагает, что данные ему будут кусками даваться и в случае необходимости он может потребовать от "условного читающего" следующий кусок — и парсишь. Есть точно только HTML-страницы — можно считать концом тег </HTML>.


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

Элемент динамического массива может иметь следующую структуру:


struct
{
   int   iSize;
   char* pData;
};
Re[6]: Обработка HTTP response, срочно нужна помощь
От: Argo1978 США  
Дата: 26.05.08 02:48
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>А html ты как/чем собрался прасить-то?


Твой парсер (http://www.codeproject.com/KB/recipes/HTML_XML_Scanner.aspx) работает и очень здорово мне помог.
Есть два момента:
1 — Могу ли я его использовать? (надеюсь, что да)
2 — Вероятно в файле xh_scanner.cpp строка 165, предполагалось использовать число 7 в качестве передаваемого пар-ра при вызове equal(tag_name,"!ENTITY",8)
Re[3]: Обработка HTTP response, срочно нужна помощь
От: The Lex Украина  
Дата: 26.05.08 10:44
Оценка:
Здравствуйте, pjBrain, Вы писали:

TL>>... пишешь парсер "кусочный" — который предполагает, что данные ему будут кусками даваться и в случае необходимости он может потребовать от "условного читающего" следующий кусок — и парсишь. Есть точно только HTML-страницы — можно считать концом тег </HTML>.


B>Зачем так сложно


Привык, понимаешь, мыслить исходя из условия ограниченности ресурсов...

B>..., когда можно просто создать простенький динамический массив в котором сохранять считываемые фрагменты.

B>Потом выделить суммарный обьем памяти необходимый для хранения всех фрагментов и слить фрагменты в единый кусок памяти.

Итого: надо будет занять двойной объем памяти.
Голь на выдумку хитра, однако...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.