Einzelnen Beitrag anzeigen

Briand
(Gast)

n/a Beiträge
 
#1

Indy Server und Client

  Alt 19. Apr 2014, 01:53
Hallo Delphianer

Ich hab heute bisschen mit den Indy’s rum gespielt und zwar mit TidTCPServer und TidTCPClient.
Ich dachte mir ich versuche mal damit einen Stream zu versenden.
Dies hat dann auch funktioniert und zwar sende ich den Stream vom Client zum Server.
Nun wollte ich auch vom Server einen Stream zum Client schicken nur der Client hat ja kein Execute Ereignis.
Habe dann bisschen gegooglet und gelesen man muss das mit einem Thread lösen.
Hab dann ein bisschen rumgebastelt und kann nun mit dem Thread so weit mal Strings empfangen.
Was allerdings nur geht wenn der Client dem Server einen String sendet und der Server das im Execute Ereignis dann zurücksendet.
Was mich auch verwirrt ist z.b im Server kann ich da nur was im Execute Ereignis senden und nicht wenn ich einen Button Klicke?
Da ich das AContext ja nur im Ereignis Execute habe.

Beispiel:
AContext.Connection.IOHandler.WriteStream(AStream, FileSize, False);

Client
Delphi-Quellcode:
 
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.ImgList, System.Win.ScktComp,
  Vcl.Buttons, JvExButtons, JvButtons, Vcl.ComCtrls, JvBackgrounds, Vcl.Imaging.pngimage,
  Vcl.Imaging.jpeg, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdExplicitTLSClientServerBase, IdFTP;

type
  TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    Edit1: TEdit;
    client: TIdTCPClient;
    BitBtn2: TBitBtn;
    BitBtn3: TBitBtn;
    BitBtn4: TBitBtn;
    BitBtn5: TBitBtn;
    BitBtn6: TBitBtn;
    procedure BitBtn1Click(Sender: TObject);
    procedure BitBtn2Click(Sender: TObject);
    procedure BitBtn3Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormDestroy(Sender: TObject);
    procedure BitBtn4Click(Sender: TObject);
    procedure BitBtn5Click(Sender: TObject);
    procedure BitBtn6Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }

  end;

type
  ULThread = class(TThread)
  procedure Execute; override;
end;

type
  DLThread = class(TThread)
  procedure Execute; override;
end;

type
  TCPREAD = class(TThread)
  procedure Execute; override;
end;



var
  Form1: TForm1;
  UL : ULThread;
  ULFilePath: String;
  ULFileName: String;
  DL : DLThread;
  DLFilePath: String;
  DLFileName: String;

  SR : TCPREAD;

implementation

Uses FileStreamUnit;

{$R *.dfm}

procedure TCPREAD.execute;
begin

while not Terminated do
begin;
form1.Caption := form1.Client.IOHandler.ReadLn;
if terminated then
begin
  break;

end;
end;

end;

procedure ULThread.execute;
var
  AStream: TFileStream;
begin
    AStream := TFileStream.Create(form1.edit1.text, fmOpenRead + fmShareDenyNone);

   // form1.edit1.Text := inttostr(astream.Size);
    try
      form1.Client.IOHandler.LargeStream := True;
      form1.Client.IOHandler.SendBufferSize := 32768;
      form1.Client.IOHandler.WriteLn('FILE'); // send command "FILE"
      form1.Client.IOHandler.WriteLn(ExtractFilename(form1.edit1.text)); // send file name
      form1.client.IOHandler.WriteLn(IntToStr(AStream.Size)); // send file size
      form1.Client.IOHandler.Write(AStream);
     finally
      FreeAndNil(AStream);
    end;
end;

procedure DLThread.execute;
var
 ftpDownStream: TFileStreamEx;
begin
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
client.Connect;
end;


procedure TForm1.BitBtn2Click(Sender: TObject);
begin
client.disconnect;
end;

procedure TForm1.BitBtn3Click(Sender: TObject);
begin
UL := ULThread.Create(True);
UL.FreeOnTerminate := false;
UL.resume
end;

procedure TForm1.BitBtn4Click(Sender: TObject);
begin
form1.Client.IOHandler.WriteLn('QUIT'); // sende irgend was damit ich was zurück erhalte
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
SR := TCPREAD.Create(true);
SR.FreeOnTerminate := true;
SR.start;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 if Client.Connected then
    Client.Disconnect;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 if Client.Connected then
    Client.Disconnect;
end;

end.

Server

Delphi-Quellcode:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Win.ScktComp, Vcl.StdCtrls, MMSystem, Shellapi,
  IdContext, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer,
  IdCmdTCPServer, IdExplicitTLSClientServerBase, IdFTPListOutput,IdFTPList, IdFTPServer,
  Vcl.ComCtrls, JvExComCtrls, JvProgressBar, Vcl.Buttons;

type
  TForm1 = class(TForm)
    server: TIdTCPServer;
    ProgressBar1: TProgressBar;
    Label1: TLabel;
    BitBtn1: TBitBtn;
    Edit1: TEdit;
    procedure serverConnect(AContext: TIdContext);
    procedure serverExecute(AContext: TIdContext);
    procedure serverDisconnect(AContext: TIdContext);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }

  end;

var
  Form1: TForm1;

implementation

uses FileStreamUnit;

{$R *.dfm}

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 if Server.Active then
    Server.Active := False;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 if Server.Active then
    Server.Active := False;
end;

procedure TForm1.serverConnect(AContext: TIdContext);
begin
form1.Caption := 'Connected'
end;

procedure TForm1.serverDisconnect(AContext: TIdContext);
begin
form1.Caption := 'Disconnect';

end;

procedure TForm1.serverExecute(AContext: TIdContext);
var
  s: string;
  AStream: TFileStreamEx;
  Filename: string;
  FileSize: Int64;

begin
  while AContext.Connection.Connected do
  begin
    s := AContext.Connection.IOHandler.ReadLn;
    if s = 'FILEthen
    begin
      a := 0;
      b := 0;
      Filename := AContext.Connection.IOHandler.ReadLn; // get filename
      FileSize := StrToInt64(AContext.Connection.IOHandler.ReadLn);
      a := filesize;

      // get filesize
      ForceDirectories(ExtractFilePath(Paramstr(0)));
      AStream := TFileStreamEx.Create('c:\0\0\test.mp4', fmCreate);
      try
        AContext.Connection.IOHandler.RecvBufferSize:= 32768;
        AContext.Connection.IOHandler.ReadStream(AStream, FileSize, False);
      finally
        FreeAndNil(AStream);
        progressbar1.Position := 100;
        label1.Caption := '100%';

      end;
    end
    else if s = 'QUITthen
    begin
      AContext.Connection.IOHandler.WriteLn('Hallo');

    end
    else
    begin
      AContext.Connection.Disconnect;
    end;
  end;
end;
end.
Das ganze funktioniert sogar mit Progressbar der Client schickt dem Server ohne Probleme die Datei.
Wie hab ich vorzugehen wenn ich das umgekehrt machen will?

Ich hoffe das mich jemand auf den Richtigen Weg führen kann

Grüsse Brian
  Mit Zitat antworten Zitat