Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Интернет и сети
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 26.02.2011, 14:36
@Vorona @Vorona вне форума
Прохожий
 
Регистрация: 25.02.2011
Сообщения: 4
Репутация: 10
Вопрос Многопотоковый "терминальный сборщик" веб-контента (IdTcpServer, TWebBrowser)

Доброго времени суток, господа! Появилась необходимость написать сетевое приложение для сбора веб-страниц. Постановка задачи следующая:
1)Приложение слушает на определённом порту.
2) На порт приходит клиент и говорит, допустим "HELLO"
3) По этой комманде должен создаваться объект TWebBrowser и при успехе в ответ приходит, допустим "READY" (какие либо ошибки пока не рассматриваю...)
4) Клиент посылает комманту "LOAD" с параметром, к примеру "http://ya.ru", на что этот объект должен соответственно среагировать
5) по коммандам HTML и DOCUMENT сервер должен отдать хтмл код и боди.иннер текст соответсвенно.
При дисконнекте объект TWebBrowser должен уничтожится.
Долго поломав голову, в качестве сервера выбрал IdTcpServer
для теста в событие камманды HELLO вписал следующее:


Код:
uses MSHTML, ActiveX;
...

procedure TForm1.IdTCPServer1HELO_COMMANDCommand(ASender: TIdCommand);
var
doc: IHTMLDocument2;
IE: TWebBrowser;
begin
memo1.Lines.Add('Client '+asender.Thread.Connection.Socket.Binding.PeerIP+':'+inttostr(asender.Thread.Connection.Socket.Binding.PeerPort)+' says: HELLO '+asender.UnparsedParams);
CoInitialize(nil);


  IE := TWebBrowser.Create(Form1);
  IE.Visible := true;
  IE.enabled := true;
  IE.Silent :=false;
  IE.Navigate('http://ya.ru');   
  memo1.Lines.Add('Waiting...');
  //while IE.Busy do sleep (200);}
  sleep (10000);
      doc := IE.Document as IHTMLDocument2;
      memo1.Lines.Add('DOM');
memo1.Lines.Add(doc.body.innerText); //Тут прога вылетает с екзепшном "Access violation at address 0046CCFB in module 'Proj.exe'. Read of address 00000000"
  //asender.Thread.Data := TObject(@IE);
end;
Причём, пробовал вручную создавать на форме данный компонент, делать с ним Navigate и пытаться выковырнуть оттуда иннертекст в один поток - прокатывало

Вопрос: что я не так делаю?

Последний раз редактировалось @Vorona, 26.02.2011 в 14:58.
Ответить с цитированием
  #2  
Старый 26.02.2011, 21:31
@Vorona @Vorona вне форума
Прохожий
 
Регистрация: 25.02.2011
Сообщения: 4
Репутация: 10
По умолчанию

Новые подробности: для теста поместил на форму 2 кнопки и TWebBrowser по событиям кнопок:

Код:
procedure TForm1.Button1Click(Sender: TObject);
begin
IE.Navigate('http://ya.ru');

end;

procedure TForm1.Button3Click(Sender: TObject);
var
doc: IHTMLDocument2;
begin
doc := IE.Document as IHTMLDocument2;
memo1.Lines.Add(doc.body.innerText);
end;
те же самые наборы комманд прописал для событий комманд инди сервера:

Код:
procedure TForm1.IdTCPServer1HELO_COMMANDCommand(ASender: TIdCommand);
var
doc: IHTMLDocument2;

begin
memo1.Lines.Add('Client '+asender.Thread.Connection.Socket.Binding.PeerIP+':'+inttostr(asender.Thread.Connection.Socket.Binding.PeerPort)+' says: HELLO '+asender.UnparsedParams);

  IE.Navigate('http://ya.ru');

end;

procedure TForm1.IdTCPServer1DOM_COMMANDCommand(ASender: TIdCommand);
var
doc: IHTMLDocument2;
begin

doc := IE.Document as IHTMLDocument2;
memo1.Lines.Add(doc.body.innerText);

end;

При этом кнопки работают как надо, а по коммандам инди - вываливается экзепшн.
Ответить с цитированием
  #3  
Старый 27.02.2011, 05:59
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,029
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

TWebBrowser - это ActiveX компонент. А для каждого клиента TIdTCPserver открывает поток. Тут то и приходит засада - для каждого нового потока надо инициализировать COM-подсистему вручную (CoInitialize, если не ошибаюсь).
Однако, весь вопрос в том - а зачем тебе TWebBrowser. Получить страничку можно и через TIdHTTP.
Ответить с цитированием
  #4  
Старый 27.02.2011, 12:37
@Vorona @Vorona вне форума
Прохожий
 
Регистрация: 25.02.2011
Сообщения: 4
Репутация: 10
По умолчанию

В данный момент у меня уже имеется програмулина, написанная на C#.NET, она вообще явно использует COM объект InternetExplorer.Application и собирает страницы из него. Прога жутко тормозит и жрёт оперативу (для каждого соединения открывается свой IE). Мне просто помимо исходного кода страницы нужно собирать иннер текст (то есть то, что видит пользователь, после всевозможных яваскриптов типа document.write). С IdHttp ни разу не работал, мне кажется иннер текст собрать ей не получится... А CoInitialize у меня в каждом потоке выполняется (в предыдущих постах она есть), без него прога даже не компилилась...
Ответить с цитированием
  #5  
Старый 28.02.2011, 17:46
mss mss вне форума
Новичок
 
Регистрация: 29.10.2010
Сообщения: 50
Репутация: 10
По умолчанию

И за каким же шишом на сервере нужен TWebBrowser ?
Это же визуальный контрол)
Кто на содержимое окна браузера на стороне сервера глазеть-то будет ?
Вполне достаточно класса CoHTMLDocument в составе mshtml.pas
Ответить с цитированием
  #6  
Старый 08.03.2011, 19:11
@Vorona @Vorona вне форума
Прохожий
 
Регистрация: 25.02.2011
Сообщения: 4
Репутация: 10
По умолчанию

Цитата:
И за каким же шишом на сервере нужен TWebBrowser ?
Нафиг не нужен.

Я попробовал чарез CoHTMLDocument. Что-то заработало, но как-то не так...
Получилось что-то вроде того:

Комманда HELLO:
Код:
          try
            CoInitialize(nil);
             IED := CoHTMLDocument.Create as IHTMLDocument2;
             IHTTP := TIdHTTP.Create(nil);
             IE_running := true;
             newMsg := 'READY';
           except
            newMsg := 'ERROR_IE_CANNOT_START';
           end;
Комманда LOAD:
Код:
          HTML := IHTTP.Get(Trim(Copy(msg, Pos(' ', msg) + 1, Length(msg)-1)));
          OleVariant(IED).write(HTML);
          //IED.open(Trim(Copy(msg, Pos(' ', msg) + 1, Length(msg)-1)), '_self','',true);
          page_loaded := true;
          newMsg := 'OK'
Комманда DOM:
Код:
          if page_loaded then
            begin
              ClientSocket.Sendln(AnsiToUtf8((IED as IHtmlDocument2).body.innerText));
              newMsg := 'THE_END_OF_DATA_TRANSFER';
            end else newMsg := 'ERROR_PAGE_NOT_LOADED';
Это всё даже почти работает, то есть по комманде DOM я вижу то, что видит пользователь, но после второго вызова LOAD с другим адресом, по комманде DOM я всё равно продолжаю получать предыдущую страницу, хотя HTML код загружается верный.
Помогите допилить это, уже замучался с этим проэктом
P.S.: додбавил IdHttp, так как c open'ом мы не сдружились, по open'у открывается IE, после чего DOM вызывает ошибку access violation
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 20:54.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter