Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > Задержка при выполнении InternetOpenURL


Автор: urix 26.12.2005, 14:22
Если, например интернета нет, или нет запрашиваемого файла, то программа надолго (30 секунд) задумывается при выполнении

hURL := InternetOpenURL(hSession,PChar(fileURL),nil,0,Flags,0);

Как БЕЗ ДЛИТЕЛЬНОЙ ЗАДЕРЖКИ проверить, есть ли доступ к нужному файлу?

--------------------------------
InternetGetConnectedState с параметром INTERNET_CONNECTION_OFFLINE не помогает, если например интернет через VPN, и отключен. То же самое и InternetQueryOption с параметром INTERNET_OPTION_CONNECTED_STATE.
--------------------------------
InternetCheckConnection(pchar(fileURL),FLAG_ICC_FORCE_CONNECTION,0) тоже задумывается на 30 секунд.
--------------------------------
InternetCheckConnection(pchar(fileURL),0,0) вообще всегда возвращает false.
--------------------------------
пробовал так:
InternetSetOption(hSession,INTERNET_OPTION_RECEIVE_TIMEOUT...
InternetSetOption(hSession,INTERNET_OPTION_SEND_TIMEOUT...
InternetSetOption(hSession,INTERNET_OPTION_CONNECT_TIMEOUT...
но тоже не помогает.

Автор: Snowy 26.12.2005, 16:35
Цитата(urix @ 26.12.2005, 14:22)
InternetCheckConnection(pchar(fileURL),0,0) вообще всегда возвращает false.

1. Перенести файл на другой хостинг - который отвечает на пинги.
2. Использовать другие способы доступа (Indy, WinSocks, etc.)
3. Запустить InternetOpenURL в отдельном потоке, который сообщит основному по мере появления результатов, не мешая работе программы.

Автор: urix 26.12.2005, 17:02
Snowy
1. Пинги хостов работают нормально. Адреса с которых качаются файлы я не могу выбирать. То есть если файл есть - он качается без проблем, а если нет, то прога задумывается.
2. посмотрю
3. Файлов иногда приходится качать много, один за другим, так что вариант с отдельным потоком для проверки не подходит.

И ещё, проблема наверное разделяется на две:
1. Сеть есть, а интернета нет
2. Интернет есть, но нужного файла по заданному url нет.

Кстати, в описании InternetCheckConnection написано что пингуется именно хост. То есть наличие конкретного файла так не узнать.
Вероятно, надо сделать какой-то TIMEOUT меньше - но какой?

Автор: Snowy 26.12.2005, 17:11
Цитата(urix @ 26.12.2005, 17:02)
И ещё, проблема наверное разделяется на две:
1. Сеть есть, а интернета нет
2. Интернет есть, но нужного файла по заданному url нет.

Нет, легко решается простым приемом - просто проверяем наличие урла, который гарантировано существует. (типа гугль).

Цитата(urix @ 26.12.2005, 17:02)
Файлов иногда приходится качать много, один за другим, так что вариант с отдельным потоком для проверки не подходит.

Просто выстраиваешь список из урлов на закачку. Можешь качать в несколько потоков или в один. Закачал - берем следующий по списку.

Цитата(urix @ 26.12.2005, 17:02)
если нет, то прога задумывается.

Ну да, ну да. Пинг тут не поможет.
Видимо винда несколько раз подряд пинговать пытается для надежности.
Честно говоря, не знаю, как это можно победить...
На Indy этот вопрос решается легко, но там встает проблема с настройками прокси.
Их нужно у пользователя спрашивать.
Добавлено @ 17:12
Цитата(urix @ 26.12.2005, 17:02)
То есть если файл есть - он качается без проблем, а если нет, то прога задумывается.

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

Автор: RA 26.12.2005, 17:57
Цитата(urix @ 26.12.2005, 14:22)
пробовал так:
InternetSetOption(hSession,INTERNET_OPTION_RECEIVE_TIMEOUT...
InternetSetOption(hSession,INTERNET_OPTION_SEND_TIMEOUT...
InternetSetOption(hSession,INTERNET_OPTION_CONNECT_TIMEOUT...
но тоже не помогает.


А чё отступился? В правильном направлении копал ....
Если покажешь что получилось в этом направлени может совмесными усилиями отыщем ошибку.

Автор: urix 26.12.2005, 18:23
Перед выполнением InternetOpenURL,
запрашиваю значения

InternetSetOption(hSession,INTERNET_OPTION_RECEIVE_TIMEOUT...
InternetSetOption(hSession,INTERNET_OPTION_SEND_TIMEOUT...
InternetSetOption(hSession,INTERNET_OPTION_CONNECT_TIMEOUT...

и ставлю новые, например в 30 раз меньше. В конце возвращаю всё на место. Разницы я не заметил.

Первоначальные значения возвращались такие:
INTERNET_OPTION_CONNECT_TIMEOUT=300000
INTERNET_OPTION_RECEIVE_TIMEOUT=не помню точно сколько нулей, но больше (360000...)
Добавлено @ 18:26
Snowy
Во многих случаях, действительно как и полагается возвращается 404, но есть исключения - в них то и проблема.

Автор: RA 26.12.2005, 22:08
Я когда-то писал подобное, заного писать не буду, но если код покажешь (весь код, чтоб я смог сам протестировать), то скорее всего помогу.

Автор: urix 26.12.2005, 22:42
RAdmin
Условия: Delphi7, локальная сеть активна, интернет выключен.

Код

uses wininet;
const  FLAG_ICC_FORCE_CONNECTION = 1;
var  WinInetEx_Max_TIMEOUT : cardinal = 10000;
......................
//думает 30 секунд, если интернет отключён
//если без FLAG_ICC_FORCE_CONNECTION, то всегда false
if internetCheckConnection(pchar('http://www.google.com'),FLAG_ICC_FORCE_CONNECTION,0) then
  Caption:='OK'
else
  Caption:='Error';
......................
Function GetFileSize(const sAppName, FileURL:string; NoCache:boolean):cardinal;
var
  hSession, hURL: HInternet;
  Flags:cardinal;
  N,BufferLen:cardinal;
  boo:boolean;
begin
  Result:=0;
  hSession := InternetOpen(PChar(sAppName), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if hSession<>nil then begin
    try
      if NoCache then Flags:=INTERNET_FLAG_RELOAD else Flags:=0;

       //если файла нет, то чтоб прога не зависала надолго
       BufferLen:=sizeof(N);
       boo:=InternetQueryOption(hSession,INTERNET_OPTION_CONNECT_TIMEOUT,@N,BufferLen); //N выходит 300000
       boo:=InternetSetOption(hSession,INTERNET_OPTION_CONNECT_TIMEOUT,@WinInetEx_Max_TIMEOUT,BufferLen);
      hURL := InternetOpenURL(hSession,PChar(fileURL),nil,0,Flags,0);  //думает 30 секунд, если интернет отключён
       boo:=InternetSetOption(hSession,INTERNET_OPTION_CONNECT_TIMEOUT,@N,BufferLen);

      //запрашиваю полный размер файла
      if hURL<>nil then result:=GetFileSize_(hURL);

    finally
      InternetCloseHandle(hSession);
    end;
  end; //hSession
end;
.......................
procedure TForm1.Button1Click(Sender: TObject);
begin
  caption:=inttostr(GetFileSize(ExtractFileName(Application.ExeName),'http://www.google.com',true));
end;

Добавлено @ 22:45
всё это в WinXP SP2

Автор: RA 27.12.2005, 15:09
urix Дейсвительно в заданных условиях wininet глючит. smile
думаю в данном случаи больше подойдёт winhttp.dll

Автор: urix 27.12.2005, 17:52
RAdmin
а для него должен быть где-то хедерный файл?

Автор: RA 28.12.2005, 10:53
Вот набор компонентов, в том числе и Http клиенты на основе wininet и winhttp, с исходниками и примерами, думаю это будет более полезно. smile
Найдёшь все что нужно для работы с winhttp.

http://torry.net/vcl/internet/http/Alcinoe30619.zip


PS: MSDN должен содержать описание всех функций winhttp.
winhttp можно совместно использовать с wininet, но что касается работы с протоколом http то winhttp надежнее.

Работать с winhttp также как и с wininet, всё почти одинаково.



Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)