Модераторы: Snowy, Poseidon, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Асинхронный вызов InternetOpenUrl 
:(
    Опции темы
hawkins
Дата 13.3.2008, 18:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 148
Регистрация: 8.9.2003

Репутация: нет
Всего: нет



У меня такая проблема. Пытаюсь скачать страницу в асинхроне,
но после чтения в цикле InternetReadFile получаю только часть
страницы, иногда вообще 0. Не асинхронный режим работает
нормально, получаю всю страницу. Ниже два кода, которые я
использую :

Не асинхронный режим:
Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, WinInet;

type
  TForm1 = class(TForm)
    btnStart: TButton;
    btnPause: TButton;
    btnStop: TButton;
    Memo1: TMemo;
    Label1: TLabel;
    Label2: TLabel;
    Memo2: TMemo;
    Label3: TLabel;
    Edit1: TEdit;
    Button1: TButton;
    Edit2: TEdit;
    procedure btnStartClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
   hSession: HINTERNET;
   hConnect: HINTERNET;
   hRequest: HINTERNET;

   userAgent: string;
  public
    { Public declarations }
    MS: TMemoryStream;

    procedure Init;
    function GetUrl(Aurl: string): Boolean;
  end;

var
  Form1: TForm1;

implementation
{$R *.dfm}
var
 userAgent: string='User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)';


procedure TForm1.Init;
begin
 Memo1.Clear;
 Memo2.Clear;
end;

procedure TForm1.btnStartClick(Sender: TObject);
begin
 btnStart.Enabled:=false;
 btnStop.Tag:=0;
 Init;
 MS:=TMemoryStream.Create;
 try
  if GetUrl(Edit1.Text) then // процедура закачки файла
   begin
    MS.Position:=0;
    Memo1.Lines.LoadFromStream(MS);  // показываем код страницы в Memo1
   end;
 finally
  MS.Free;
  btnStart.Enabled:=true;
 end;

end;


function TForm1.GetUrl(Aurl: string): Boolean;
var
 Buffer: array [0..1023] of byte;
 lBytesToRead, lReadBytes: cardinal;
 rst: Boolean;
 lDataSize: DWORD;

  procedure CloseConnect;
   begin
    if Assigned(hRequest) then InternetCloseHandle(hRequest);
     hRequest:=nil;
    if Assigned(hConnect) then InternetCloseHandle(hConnect);
     hConnect:=nil;
    if Assigned(hSession) then InternetCloseHandle(hSession);
     hSession:=nil;
   end;

begin

  result:=false;
  if not Assigned(hSession) then
   hSession:=InternetOpen(PChar(userAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if not Assigned(hSession) then  exit;

  hRequest:=InternetOpenUrl(hSession,Pchar(Aurl),'',0,INTERNET_FLAG_RELOAD or INTERNET_FLAG_NO_CACHE_WRITE, 0);

  if Assigned(hRequest) then
   if InternetQueryDataAvailable(hRequest, lDataSize,0,0) then
    begin
     result:=true;
     lBytesToRead:=length(Buffer);
     repeat
      Application.ProcessMessages;
      if btnStop.Tag=1 then
       begin
        Result:=false;
        break;
       end;
      lReadBytes:=0;
      rst:=InternetReadFile(hRequest, @Buffer, lBytesToRead, lReadBytes);
      if rst and (lReadBytes>0) then MS.WriteBuffer(Buffer, lReadBytes);

     until lReadBytes<=0;
    end;

 CloseConnect;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Lines.SaveToFile(Edit2.Text);
end;

end.




Асинхронный режим:
Код

unit Unit1;
// закачка файла через InternetOpenURL в асинхроне

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, WinInet;

type
  TForm1 = class(TForm)
    btnStart: TButton;
    btnPause: TButton;
    btnStop: TButton;
    Memo1: TMemo;
    Label1: TLabel;
    Label2: TLabel;
    Memo2: TMemo;
    Label3: TLabel;
    Edit1: TEdit;
    Button1: TButton;
    Edit2: TEdit;
    procedure btnStartClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
   hSession: HINTERNET;
   hConnect: HINTERNET;
   hRequest: HINTERNET;

   FConnectClosing: Boolean;
   FConnectClosed: Boolean;
   FHandleClosing: Boolean;
   FRespReceived: Boolean;
   FBytesRead: integer;
   FContext: integer;

   userAgent: string;
  public
    { Public declarations }
    MS: TMemoryStream;

    procedure Init;
    function GetUrl(Aurl: string): Boolean;
  end;

var
  Form1: TForm1;

implementation
{$R *.dfm}
var
 userAgent: string='User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)';


procedure TForm1.Init;
begin
 Memo1.Clear;
 Memo2.Clear;
end;

procedure TForm1.btnStartClick(Sender: TObject);
begin
 btnStart.Enabled:=false;
 btnStop.Tag:=0;
 Init;
 MS:=TMemoryStream.Create;
 try
  if GetUrl(Edit1.Text) then  // процедура закачки
   begin
    MS.Position:=0;
    Memo1.Lines.LoadFromStream(MS);  // показываем код страницы в Memo1
   end;
 finally
  MS.Free;
  btnStart.Enabled:=true;
 end;

end;

// процедура обратного вызова
procedure InternetStatusCallBack( 
   AInetHandle: HINTERNET;
   AContext: Pointer;
   AInternetStatus: DWORD;
   AStatusInformation: Pointer;
   AStatusInfoSize: DWORD
  ); stdcall;
begin

 case AInternetStatus of
  INTERNET_STATUS_CLOSING_CONNECTION:
    Form1.FConnectClosing:=true;
  INTERNET_STATUS_CONNECTION_CLOSED:
    Form1.FConnectClosed:=true;
  INTERNET_STATUS_HANDLE_CLOSING:
    Form1.FHandleClosing:=true;

  INTERNET_STATUS_HANDLE_CREATED:
   Form1.hConnect:=HINTERNET(PInternetAsyncResult(AStatusInformation)^.dwResult);

  INTERNET_STATUS_REQUEST_COMPLETE:
   Form1.hRequest:=HINTERNET(PInternetAsyncResult(AStatusInformation)^.dwResult);

  INTERNET_STATUS_RESPONSE_RECEIVED:
   begin
    Form1.FBytesRead:=Cardinal(AStatusInformation^);
    Form1.FRespReceived:=true;
   end;

 end;
end;


function TForm1.GetUrl(Aurl: string): Boolean;
var
 Buffer: array [0..1023] of byte;
 lBytesToRead, lReadBytes: cardinal;
 rst: Boolean;
 lDataSize: DWORD;
 sum: integer;

  procedure CloseConnect;
   begin
    if Assigned(hRequest) then InternetCloseHandle(hRequest);
     hRequest:=nil;
    if Assigned(hConnect) then InternetCloseHandle(hConnect);
     hConnect:=nil;
    if Assigned(hSession) then InternetCloseHandle(hSession);
     hSession:=nil;
   end;

begin
  result:=false;
  if not Assigned(hSession) then
   hSession:=InternetOpen(PChar(userAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, INTERNET_FLAG_ASYNC);
  if not Assigned(hSession) then  exit;

  InternetSetStatusCallback(hSession, @InternetStatusCallBack);
  FConnectClosing:=false;
  FConnectClosed:=false;
  FHandleClosing:=false;
  Form1.FRespReceived:=false;
  hRequest:=nil;
  sum:=0;

  InternetOpenUrl(hSession,Pchar(Aurl),'',0,INTERNET_FLAG_RELOAD or INTERNET_FLAG_NO_CACHE_WRITE or INTERNET_FLAG_KEEP_CONNECTION, Cardinal(@FContext));

  while true do // цикл ожидания вызова callback функции
  begin
   Application.ProcessMessages;
   if btnStop.Tag=1 then
   begin
    CloseConnect;
    break;
   end;

   if Form1.FRespReceived  then  //and (Form1.hRequest<>nil)
   begin   
     break;
   end;
   sleep(100);
  end;

  if Assigned(hRequest) then
   if InternetQueryDataAvailable(hRequest, lDataSize,0,0) then
    begin
     result:=true;
     lBytesToRead:=length(Buffer);
     repeat
      Application.ProcessMessages;
      if btnStop.Tag=1 then // если нажата кнопка стоп выходим
       begin
        Result:=false;
        break;
       end;
      lReadBytes:=0;
      rst:=InternetReadFile(hRequest, @Buffer, lBytesToRead, lReadBytes);
      if (lReadBytes>0) then MS.WriteBuffer(Buffer, lReadBytes);

      //-- Debug
       sum:=sum+lReadBytes;
       Memo2.Lines.Add('lReadBytes='+IntToStr(lReadBytes));
      //---------

     until lReadBytes<=0;
    end;

 Memo2.Lines.Add('sum='+IntToStr(sum)); // debug сколько всего скачано байт
 CloseConnect;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Lines.SaveToFile(Edit2.Text);
end;

end.


PM MAIL   Вверх
MetalFan
Дата 13.3.2008, 18:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 14
Всего: 128



Дело в том, что InternetReadFile также работает в асинх.режиме, т.е. может возвращать управление почти сразу не ожидая получения всех данных...
как-то я с этим ковырялся... но в свой компонент эту асинхронность так и не прикрутил.


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Сети"
Snowy
Poseidon
MetalFan

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Snowy, Poseidon, MetalFan.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0485 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.