Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Porting old Delphi2007 application using TServerSocket....
#12
I managed to get the server working with your help! Thanks for that!

Now I have a new task and this is to port the client application to FreePascal/Lazarus from Delphi.
Again I need to replace an old socket component with an Indy10 implementation, i.e. I need to create a receive event for TIdTcpClient...

In this case I have found a number of examples which for some reason do not work (Lazarus complains) which use a thread to read incoming data and then use an event function to feed the main application.
So I decided to make a class that handles this with Indy10 and implements the functions used by the earlier solution.
This uses a read thread as described in several old forum posts...
Below is how far I have come but I have gotten stuck concerning how to best retrieve the data in the thread Execute and supply it to the client via the event procedure.

Questions:
What should I put into the thread execute function on data reception to transfer it into the event?
Should I read the data in the thread or should I just push a notification that data are available and let the implementation of the event procedure read from the socket?

Here is my current (incomplete) state of the code:
Code:
unit TcpClientComm;
{******************************************************************************
* This is an attempt to use Indy10 TIdTcpClient object as a TCP/IP connection
* while providing an event driven model for receiving data from the server.
*
*
*******************************************************************************}

{$IFDEF FPC}
  {$MODE Delphi}
{$ENDIF}

interface

uses
  Classes,
  SysUtils,
  IdBaseComponent,
  IdComponent,
  IdTCPConnection,
  IdTCPClient,
  IdGlobal
  ;

type
  TCommRxEvent = procedure (Sender: TObject; Data: string) of object;

  { TReadingThread }

  TReadingThread = class(TThread)
  protected
  FConn: TIdTCPConnection;
    FOnRxData: TCommRxEvent;
  procedure Execute; override;
  public
  constructor Create(ACon: TIdTCPConnection);
    property OnRxData: TCommRxEvent read FOnRxData write FOnRxData;
  end;

  { TTcpClientComm }

  TTcpClientComm = class(TObject)
  private
    FConn: TIdTCPClient;
    FReadThread: TReadingThread;
    FOnRxData: TCommRxEvent;
    FLastError: string;
    function GetConnected: boolean;
  public
    constructor Create;
    destructor  Destroy; override;
    property OnRxData: TCommRxEvent read FOnRxData write FOnRxData;
    property LastError: string read FLastError;
    property Connected: boolean read GetConnected;
    procedure Connect(Host: string; Port: word);
    procedure Disconnect;
    function  WriteString(Data: string): boolean; overload;
    function  WriteData(Data: TIdBytes): boolean; overload;
  end;

implementation

{ TTcpClientComm }

function TTcpClientComm.GetConnected: boolean;
begin
  Result := FConn.Connected;
end;

constructor TTcpClientComm.Create;
begin
  FConn := TIdTCPClient.Create(NIL);
  FReadThread := TReadingThread.Create(FConn);
end;

destructor TTcpClientComm.Destroy;
begin
  inherited Destroy;
end;

procedure TTcpClientComm.Connect(Host: string; Port: word);
begin
  FConn.Connect(Host, Port);
end;

procedure TTcpClientComm.Disconnect;
begin
  FConn.Disconnect;
end;

function TTcpClientComm.WriteString(Data: string): boolean;
var
  DataBytes: TIdBytes;
begin
  Result := false;
  FLastError := 'No data';
  if Length(Data) = 0 then exit;

  SetLength(DataBytes, Length(Data));
  Move(Data[1], DataBytes[0], Length(Data));
  Result := WriteData(DataBytes);
end;

function TTcpClientComm.WriteData(Data: TIdBytes): boolean;
begin
  Result := false;
  FLastError := 'No data';
  if Length(Data) = 0 then exit;

  if not FConn.Connected then
  begin
    FLastError := 'Not connected';
    exit;
  end;

  try
    FConn.IOHandler.Write(Data);
    Result := true;
  except
    on E: Exception do
      FLastError := E.Message;
  end;
end;

{ TReadingThread }

procedure TReadingThread.Execute;
begin
while not Terminated do
begin
  if FConn.IOHandler.CheckForDataOnSource(10) then
    if FConn.IOHandler.InputBuffer.Size > 0 then
    begin
      // read bytes from FConn up
      // to InputBuffer.Size bytes ...
      //
      // process bytes as needed ...
    end;
  end;
end;
constructor TReadingThread.Create(ACon: TIdTCPConnection);
begin
  FConn := ACon;
  inherited Create(False);
end;
Reply


Messages In This Thread
RE: Porting old Delphi2007 application using TServerSocket.... - by BosseB - 08-28-2020, 08:53 PM

Forum Jump:


Users browsing this thread: 2 Guest(s)