Страница 1 из 1

Передать поток по сети через indy компоненты

СообщениеДобавлено: 31.01.2012 18:35:25
dark
Пытаюсь написать аналог радмин/vnc.
Помогите решить проблему, плз... Пишу клиент-сервер на lazarus 0.9.30.2. Использую компоненты idTCPClient и idTCPServer (indy 10.5.8). Уже запутался... Не могу сообразить: как как создать поток в idTCPServer, записать в него содержимое компонента Image и передать с сеть, и как потом прочитать этот поток на клиенте, и передать в Image клиента. Пробовал примеры из делфи, но они не подходят.
Код сервера:
Код: Выделить всё
unit Server;
{$mode objfpc}{$H+}
interface
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  LCLIntf, LCLType, IdTCPServer, IdCustomTCPServer, IdContext, idSocketHandle;
type
  { TForm1 }
  TForm1 = class(TForm)
    Button1: TButton;
    IdTCPServer1: TIdTCPServer;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure IdTCPServer1Execute(AContext: TIdContext);

  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }

//--- включаем сервер ---
procedure TForm1.FormCreate(Sender: TObject);
begin
idTCPServer1.Active:= true;
end;
//--- отключаем сервер ---
procedure TForm1.FormDestroy(Sender: TObject);
begin
idTCPServer1.Active:= false;
end;
//--- получаем картинку удалённого раблчего стола ---
procedure TForm1.Button1Click(Sender: TObject);
var
MyJpeg: TJpegImage;
ScreenDC: HDC;
My_SCR: TStream;
begin
idTCPServer1.Contexts.Create;
MyJpeg:= TJpegImage.Create;
My_SCR:= TMemoryStream.Create;
ScreenDC:= GetDC(0);
MyJpeg.LoadFromDevice(ScreenDC);
My_SCR.Position:= 0;
MyJpeg.SaveToStream(My_SCR);
My_SCR.Free;
MyJpeg.Free;
end;
//--- отправляем картинку ---
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
com_str: string;
begin
with AContext.Connection do
  begin
    Button1.Click;
  end; 
end;

Код клиента
Код: Выделить всё
unit Client;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls, LCLIntf, LCLType, IdTCPClient, idSocketHandle;

type
  { TForm1 }
  TForm1 = class(TForm)
    Bevel1: TBevel;
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    GroupBox1: TGroupBox;
    IdTCPClient1: TIdTCPClient;
    Image1: TImage;
    Label1: TLabel;
    Memo1: TMemo;
    Timer1: TTimer;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure IdTCPClient1Connected(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }

//--- подключаемся к серверу ---
procedure TForm1.Button1Click(Sender: TObject);
begin
if Edit1.Text = ''then
  Memo1.Lines.Add('Ввидите IP адрес сервера')
else
  begin
   IdTCPClient1.Host:= Edit1.Text;
   try
    Memo1.Lines.Add('Соединение устанавливается...');
    IdTCPClient1.Connect(IdTCPClient1.Host, IdTCPClient1.Port);
    Memo1.Lines.Add('Соединение установлено!');
   except
    Memo1.Lines.Add('Не удалось соединиться с сервером')
   end;
  end;
end;
//--- Действия выполняемые при соединении с сервером ---
procedure TForm1.IdTCPClient1Connected(Sender: TObject);
begin
  Edit1.Enabled:= False;
  //начинаем периодически запрашивать данные с сервера
  Timer1.Enabled:= True;
  //выполним первый запрос, не дожидаясь срабатыввания таймера
  Timer1Timer(nil);
end;
//--- Действия при отсоединении от сервера ---
procedure TForm1.Button2Click(Sender: TObject);
begin
Memo1.Lines.Add('Соединение разрывается');
idTCPClient1.Disconnect;
Memo1.Lines.Add('Соединение разорвано');
Edit1.Enabled:= True;
Timer1.Enabled:= False;
end;
//--- Запрос и обработка данных, полученных от сервера ---
procedure TForm1.Timer1Timer(Sender: TObject);
var
MyJpeg: TJpegImage;
stream: TStream;
// My_SCR: TStream;
begin
with idTCPClient1 do
  begin
  // WriteLn('get_screen');
   //--- получаем снимок ---
   MyJpeg:= TJpegImage.Create;
   stream:= TMemoryStream.Create;
  // idTCPClient1.Socket.ReadLn;
  // ReadStream(stream);
  // stream.Position := 0;
  // MyJpeg.LoadFromStream(stream);
   stream.Position:= 0;
  // My_SCR.Position := 0;
  // MyJpeg.SaveToStream(stream);
   Image1.Parent.DoubleBuffered:= true;
   Image1.Picture.LoadFromStream(stream);
   MyJpeg.Free;
   stream.Free;
  end;
end;
end.

Re: Передать поток по сети через indy компоненты

СообщениеДобавлено: 31.01.2012 19:15:27
Odyssey
В соседней теме есть пример, возможно это то что нужно.

Re: Передать поток по сети через indy компоненты

СообщениеДобавлено: 01.02.2012 07:27:20
dark
Эх... совсем забыл дополнить свой вопрос данным... Вышеуказанные клиент и сервер пишутся под win32-win64. Поэтому часть кода не работает.
Эта часть вроде для Unix/Linux:
Код: Выделить всё
 
{$IFDEF UNIX}
cthreads,
{$ENDIF}

А эта процедура выдаёт ошибку:
Код: Выделить всё
procedure TForm1.IdTCPServer1Execute(aThread: TIdContext);

типа: var name changes AContext=>aThread (то есть вместо aThread должен быть AContext)...
Но когда делаю так:
Код: Выделить всё
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);

то непонятно с какими парами Readln/Writeln нужно работать в процессе записи данных в поток и чтении оных из потока...
Так что примеры под *.nix тоже неподходят... нужно именно под винду (и именно на лазарусе а не на делфи)...

Re: Передать поток по сети через indy компоненты

СообщениеДобавлено: 01.02.2012 21:01:50
B4rr4cuda
Имхо, как то рановато Вам аналог Внц или радмина писать...
Код: Выделить всё
{$IFDEF UNIX}
cthreads,
{$ENDIF}

Директива компилятора, указывающая в случае компиляции под юниксовые системы юзать модуль cthreads. В иных случаях он не будет использован.

procedure TForm1.IdTCPServer1Execute(aThread: TIdContext);

Возможно, нужно подключить модуль от инди, где определен тип TIdContext. Название уж не помню, давно инди ковырял, но подобное выпадало.. Кстати говоря, лучше в сторону Synapse смотреть, хотя вам лучше в сторону LNet компонентов.

то непонятно с какими парами Readln/Writeln нужно работать в процессе записи данных в поток и чтении оных из потока..

смотреть тут

Re: Передать поток по сети через indy компоненты

СообщениеДобавлено: 02.02.2012 08:04:03
dark
Что бы пропала ошибка в прогцедуре
Код: Выделить всё
procedure TForm1.IdTCPServer1Execute(aThread: TIdContext);

просто заменяю aThread на AContext... Насколько я понял (в indy на lazarus под windows) вместо aThread для передачи потока используется AContext. Тогда процедура имеет вид
Код: Выделить всё
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);

и при компиляции не выдаёт ошибок... Значит данные передаются в AContext... но как их туда записать, и потом прочитать оттуда...
Такое ощущение, что в indy для лазаря под винду просто нет возможности работы с потоками...
Может я в чём-то ошибаюсь???

Re: Передать поток по сети через indy компоненты

СообщениеДобавлено: 02.02.2012 08:58:17
Brainenjii
эм, а какая разница как назвать параметр? Здесь же тип же тот же - TIdContext же. Соответственно все методы и свойства остались теми же... И запись с чтением, внезапно, осуществляется так же, как в примере. Просто привычка называть параметр Execute aThread'ом ещё со врёмен Indy7-9.
Пару лет назад активно пользовал Indy и на юниксах, и на винде. Всё работало исправно.
Брать indy стоит отсюда.

Re: Передать поток по сети через indy компоненты

СообщениеДобавлено: 02.02.2012 09:49:14
Padre_Mortius
Буквально с полгода назад на глаза попадался компонент, реализующий функционал VNC-сервера и клиента. Может стоит им воспользоваться?

Re: Передать поток по сети через indy компоненты

СообщениеДобавлено: 02.02.2012 10:10:12
dark
Brainenjii - спасибо, натолкнул на мысль... получилось передать текст (пока без создания дополнительных потоков)...
только вот при в мемо1 и у клиента и у сервера переданный текс отображается в виде "????????????'.
Padre_Mortius - я это exe'шник ещё года 2-3 назад скачивал... это не компонент... а полноценный клиент для ВНЦ... и никаких исходников там нету, к сожаления... Находил компонент для делфей... но в нем файлов для установки не хватало...

Добавлено спустя 10 минут 19 секунд:
Padre_Mortius - ссори, нашёл код - http://dsk.git.sourceforge.net/git/gitweb.cgi?p=dsk/dskvnc;a=commit;h=1c7874f69c531981220800e85daf0b76a357015c... раньше не натыкался... только екзешник находил...

Re: Передать поток по сети через indy компоненты

СообщениеДобавлено: 03.02.2012 21:49:53
B4rr4cuda
dark писал(а):только вот при в мемо1 и у клиента и у сервера переданный текс отображается в виде "????????????'.

Кстати да.. Беда с кодировкой будет вылезать постоянно и хз решается ли она.
Я решил никогда больше не юзать инди, когда после недели активного секса с попыткой подключить и нормально использовать SSL с инди, да чтоб кодировочка не доставляла проблем, да чтоб потоки не отваливались, написал за день-два требуемый модуль, используя Synapse.

Re: Передать поток по сети через indy компоненты

СообщениеДобавлено: 08.02.2012 20:11:44
dark
хм... а если при передаче-приёме текстовых сообщений попробовать UtfToSys/SysToUtf ?.. сам пока не пробовал... руки не доходят...

Re: Передать поток по сети через indy компоненты

СообщениеДобавлено: 15.02.2012 21:32:36
B4rr4cuda
dark писал(а):хм... а если при передаче-приёме текстовых сообщений попробовать UtfToSys/SysToUtf ?.. сам пока не пробовал... руки не доходят...

Не.. инфа бьется намертво, т.е. не меняется кодировка, а банально знаки вопросов приходят) Это стало последней каплей, после которого synapse намертво занял позицию юзаемой сетевой библиотеки.