[ gajo2 @ 16.10.2006. 20:39 ] @
Pozdrav,

Trenutno radim na jednom programu sto proverava da li neki URL postoji. Tj. upisem neki URL i on ili vraca da je sve ok ili da je 404, tj. sajt ne postoji/ne radi.
Medjutim, desila se situacija da poneki sajtovi rade, medjutim treba im dosta vremena (minuti) da odgovore nazad. Za svo to vreme meni se thread za proveravanje blokira. Na kraju vraca da je sve ok, tj. sajt postoji. Medjutim meni bi bilo zgodno da ako nema odgovora posle 1 minuta, da to ispisem i da nastavim sa ostalim sajtovima.

E sada trazio sam po Internetu vec skoro pola dana i nisam nasao nista sto bi radilo. Prema MSN-u i jos ponekim sajtovima resenje je da se uradi sledece:

Code:
InternetSetOption(hConnect, INTERNET_OPTION_CONNECT_TIMEOUT, @Timeout, SizeOf(Timeout));


Timeout: DWORD je broj milisekundi posle cega se konekcija odbacuje. Po default-u je beskonacan.

Probao sam da podesim timeout na 1, tj. konekcija uvek treba odmah da se odbaci, medjutim izgleda da ova naredba nema nikakvog efekta. Program nastavlja da radi kako je vec radio.

Pomislio sam mozda je i broj retry-ova beskonacan, pa sam i to podesio na 1 ovako:

Code:
InternetSetOption(hConnect, INTERNET_OPTION_CONNECT_RETRIES, @Timeout, SizeOf(Timeout));


ali se nista nije desilo.
Jel ima neko ideju sta da uradim? Evo kompletne funkcije:

Code:
function GetUrlStatusCode(Url: string; var time: TDateTime): integer;
var
  hInet: HINTERNET;
  hConnect: HINTERNET;
  infoBuffer: array [0..512] of char;
  dummy: DWORD;
  bufLen: DWORD;
  Timeout: DWORD;
  okay: LongBool;
  g_Statuscode: string;
  sAppName: string;
begin
  time := now;
  sAppName := ExtractFileName(Application.ExeName);

  hInet := InternetOpen(PChar(sAppName),
                        INTERNET_OPEN_TYPE_PRECONFIG,
                        nil,
                        nil,
                        0);

  hConnect := InternetOpenUrl(hInet,PChar(Url),nil,0, INTERNET_FLAG_NO_UI,0);

  if not Assigned(hConnect) then
    g_Statuscode := '404'
  else begin
    dummy := 64;
    Timeout := $1;
    InternetSetOption(hConnect, INTERNET_OPTION_CONNECT_TIMEOUT, @Timeout, SizeOf(Timeout));
    Timeout := $1;
    InternetSetOption(hConnect, INTERNET_OPTION_CONNECT_RETRIES, @Timeout, SizeOf(Timeout));
    dummy := 0;
    bufLen := Length(infoBuffer);
    okay := HttpQueryInfo(hConnect,HTTP_QUERY_STATUS_CODE, @infoBuffer[0],bufLen,dummy);
    if not okay then
      g_Statuscode := '404'
    else
      g_Statuscode := infoBuffer;

    InternetCloseHandle(hConnect);
  end;
  InternetCloseHandle(hInet);

  result := StrToInt(g_Statuscode)
end;

Dakle, ne downloadujem celu stranicu, nego samo proveravam da li je 404 ili nije.
Kada bi timeout radio, onda ova funkcija:

Code:
okay := HttpQueryInfo(hConnect,HTTP_QUERY_STATUS_CODE, @infoBuffer[0],bufLen,dummy);


bi uvek vracala false, tj. okay bi uvek bio false i funkcija bi uvek vracala 404. To se, medjutim, ne desava.

Jel zna neko pomoci? Hvala unapred,
Gajo
[ _deran_ @ 16.10.2006. 22:26 ] @
Probaj TIdIcmpClient. Pinguj port 80 pa vidi da li vraca, imas i receivetimeout.
[ gajo2 @ 16.10.2006. 22:43 ] @
Skinuo sam paket za Delphi 5 ali ne mogu nikako da ga instaliram. Nesto se buni da se FileCtrl nalazi i u Indy-ovom i u Vclx50 paketu, pa ne moze da radi. Pa sam odlucio da sve radim preko WinAPI-ja (sad je vec kasno da se vratim na Indy).

U svakom slucaju uspeo sam da resim problem. Thread koji radi provere stvori jedan novi thread, koji poziva GetUrlStatusCode(). Za to vreme ovak glavni thread ceka i proverava da li je ovaj zavrsio svoje, ili je vec isteklo vreme. A ako je isteklo, thread se prekida.
Ne znam da li ovako dolazi do curenja memorije, ali izgleda da radi. Program ne pada ni kada rade 20 threadova nad 1000 URL-ova. Jos cu testirati, pa cemo videti. Ovo jeste ruzno resenje, ali jbga.

Inace setovanje timeout-a onako kako sam ja hteo izgleda ne moze nikako, zbog nekog baga u Windowsu. Barem na ovom sajtu tako pise: http://www.kbalertz.com/kb_176420.aspx
[ savkic @ 17.10.2006. 09:39 ] @
Pogledaj TIdHTTP komponentu (mislim da se tako zove) iz Indy paketa. Tamo imaš opciju da podesiš timeout.
[ Nemanja Avramović @ 17.10.2006. 17:47 ] @
Ubaci rutinu za proveravanje u poseban thread, tako to nikako neće uticati na performanse tvoje aplikacije. Evo ti kako da započneš:

Code:
function NekiThread(AParameter : pointer) : DWORD; // Moze i obicna procedure NekiThread, zavisno od toga da li ces prosledjivati neki parametar fji
begin
  repeat
    // Ovo ti kao neki loop, tu ide rutina koja se ponavlja
  until 1 <> 1;
end;

var
  TID : DWORD;

begin
  BeginThread(nil, 0, @NekiThread, nil, 0, TID);
end.