title: The connection does not timeout while downloading file from internet
body: <p>Related to a post of mine ( <a href="https://stackoverflow.com/questions/3122306/how-to-retrieve-a-file-from-internet-via-http">How to retrieve a file from Internet via HTTP?</a> ) about how to easily and robustly download a file from Internet, I have found a possible solution - however is not working as it was supposed to work.</p>
  
  <p>According to MS documentation, the code below is supposed to time-out at 500ms after I disconnect myself from internet. However, it looks like it totally ignores the 'INTERNET_OPTION_RECEIVE_TIMEOUT' setting. The application freezes during download. It takes about 20-30 to this function to realize that there the Internet connection is down and to give the control back to the GUI.</p>
  
  <p>Anybody knows why?</p>
  
  <pre><code>function GetBinFileHTTP (const aUrl: string; const pStream: TStream; wTimeOut: Word= 500; wSleep: Word= 500; wAttempts: Word= 10): Integer;
  CONST
    BufferSize = 1024;
  VAR
    hSession, hService: HINTERNET;
    Buffer     : array[0..BufferSize-1] of Char;
    dwBytesRead, dwBytesAvail: DWORD;
    lSucc        : LongBool;
    lRetries, dwTimeOut: Integer;   
  begin
   Result:= 0;
   if NOT IsConnectedToInternet then
    begin
     Result:= -1;
     EXIT;
    end;
  
   hSession := InternetOpen(PChar(ExtractFileName(Application.ExeName)), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);  { The INTERNET_OPEN_TYPE_PRECONFIG flag specifies that if the user has configured Internet Explorer to use a proxy server, WinInet will use it as well. }
   if NOT Assigned(hSession) then
    begin
     Result:= -4;
     EXIT;
    end;
  
   TRY
     hService := InternetOpenUrl(hSession, PChar(aUrl), nil, 0, INTERNET_FLAG_RELOAD, 0);
     if NOT Assigned(hService) then Exit;
     TRY
       FillChar(Buffer, SizeOf(Buffer), 0);
  
       { Set time out }
       dwTimeOut:= wTimeOut;
       InternetSetOption(hService, INTERNET_OPTION_RECEIVE_TIMEOUT, @dwTimeOut, SizeOf(dwTimeOut));   { use INTERNET_FLAG_RELOAD instead of NIL to redownload the file instead of using the cache }
  
  
       InternetSetOption(hService, INTERNET_OPTION_CONNECT_TIMEOUT, @dwTimeOut, SizeOf(dwTimeOut));
  
       REPEAT
         lRetries := 0;
  
         REPEAT
           lSucc:= InternetQueryDataAvailable( hService, dwBytesAvail, 0, 0);
           if NOT lSucc
           then Sleep( wSleep );
           if lRetries &gt; wAttempts
           then Result:= -2;
         UNTIL lSucc OR (Result= -2);
  
         if NOT InternetReadFile(hService, @Buffer, BufferSize, dwBytesRead) then
          begin
            Result:= -3;                                                          { Error: File not found/File cannot be downloaded }
            EXIT;
          end;
  
         if dwBytesRead = 0
         then Break;
  
         pStream.WriteBuffer(Buffer[0], dwBytesRead);
  
       UNTIL False;
     FINALLY
       InternetCloseHandle(hService);
     end;
   FINALLY
     InternetCloseHandle(hSession);
   end;
  
   Result:= 1;
  end;
  </code></pre>
  
  <p>Here is the documentation:</p>
  
  <pre><code>{
  
  INTERNET_OPTION_CONNECT_TIMEOUT         Sets or retrieves an unsigned long integer value that contains the time-out value to use for Internet connection requests. If a connection request takes longer than this time-out value, the request is canceled. When attempting to connect to multiple IP addresses for a single host (a multihome host), the timeout limit is cumulative for all of the IP addresses. This option can be used on any HINTERNET handle, including a NULL handle. It is used by InternetQueryOption  and InternetSetOption.
  INTERNET_OPTION_RECEIVE_TIMEOUT         Sets or retrieves an unsigned long integer value that contains the time-out value to receive a response to a request.      If the response takes longer than this time-out value, the request is canceled. This option can be used on any HINTERNET handle, including a NULL handle. It is used by InternetQueryOption and InternetSetOption. For using WinInet synchronously, only the default value for this flag can be changed by calling InternetSetOption and passing NULL in the hInternet parameter.
                    INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT - Identical to INTERNET_OPTION_RECEIVE_TIMEOUT. This is used by InternetQueryOption and InternetSetOption.
  }
  </code></pre>
  
  <p>Edit:
  I disconnect the Internet by unplugging the cable or (for wireless) from software AFTER the application starts the download (I chose to download large file). It simulates the web site going offline.</p>