WinHttpReceiveResponse ERROR_WINHTTP_TIMEOUT
От: Lonkar  
Дата: 16.03.15 15:06
Оценка:
Возникла необходимость при использовании библиотеки WinHTTP ограничить время ожидания ответа.
Для этого использую функцию WinHttpSetTimeouts.
Проблема в том, что при небольших значениях таймаут срабатывает очень не точно.

Например, для этого кода
#include <Windows.h>
#include <WinHttp.h>
#include <iostream>
#include <ctime>

int main()
{
   for( int delay = 0; delay < 2000; delay += 100 )
   {
      clock_t start = clock();
      HINTERNET hInternet = WinHttpOpen( L"", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, NULL, NULL, 0 );
      HINTERNET hConnect  = WinHttpConnect( hInternet, L"httpbin.org", 80, 0 );
      HINTERNET hRequest  = WinHttpOpenRequest( hConnect, L"GET", L"/delay/2", NULL, NULL, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_REFRESH );
      // set timeout - 1 second
      WinHttpSetTimeouts( hRequest, 1000, 1000, 1000, 1000 );
      WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, NULL );
      WinHttpReceiveResponse( hRequest, NULL );

      DWORD last_error = GetLastError();
      if( last_error = ERROR_WINHTTP_TIMEOUT ) // 12002
         std::cout << float(clock() - start)/CLOCKS_PER_SEC << std::endl;
      else
         std::cout << "UNEXPECTED ERROR " << last_error << std::endl;

      WinHttpCloseHandle( hRequest );
      WinHttpCloseHandle( hConnect );
      WinHttpCloseHandle( hInternet );
      Sleep( delay );
   }
   return 0;
}

получаю следующий вывод
1.008
0.994
0.9
0.8
0.699
0.599
0.5
0.4
0.301
0.198
1.001
1.001
0.996
0.799
0.699
0.599
0.499
0.398
0.304
0.195

Т.е. вместо ожидаемых 1000мс, таймаут иногда срабатывает через 195мс, что в 5 раз быстрее ожидаемого.
Причем первый запрос всегда отрабатывает как надо. Проблема проявляется на последующих, не смотря на то, что все хэндлы закрыты.
Сталкивался кто-нибудь с подобной проблемой? Может можно как-то подкрутить таймер проверки таймаута?
winhttp
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.