How to set up a simple connection between TIdTcpClient and TIdTcpServer to send a string from client to server?

22,307

Solution 1

Server:
Anywhere in your Create, Initialize function:

FIndySrv:=TIdTCPServer.Create(nil);
FIndySrv.DefaultPort:=50000;
FIndySrv.OnExecute:=DoOnIndyExecute;
FIndySrv.Active:=true;

The OnExecute:

procedure TForm1.DoOnIndyExecute(AContext: TIdContext);
var recv:string;
begin
  recv := AContext.Connection.Socket.ReadLn;
  // ...
end;

Client:

FIndyClient:=TIdTCPClient.Create(nil);
FIndyClient.Host:='localhost';
FIndyClient.Port:=50000;
FIndyClient.Connect;
FIndyClient.Socket.WriteLn('Hallo Welt!');

Solution 2

Since the question is particular asking how to send from a VCL Component to another VCL Component and it's likely that this question will be asked/searched again.
Using IdTCPClient is as easy at it can be.
You will just have to assign Host and Port , open the connection and Write the content to the socket of IdTCPClient.
Since you will have to be able to read the data at the serverside and there is no need for a protocol (e.g. sending the length of the content as integer to let the server know how much he has to read) the most simple way is to use Socket.WriteLn to be able to use Socket.ReadLn at serverside.
Note that the OnExecute Event of IdTCPServer is run in an own threadcontext, so you will have to synchronize your calls to the mainthread.
One of the possible ways to do this is to use a descendant of TIDSync.

uses IDSync;

type
  TMySync = Class(TIDSync)
  private
    FContent: String;
    FDestination: TStrings;
    Constructor Create(const Content: String; Destination: TStrings); overload;
  protected
    Procedure DoSynchronize; override;
  public
  End;

constructor TMySync.Create(const Content: String; Destination: TStrings);
begin
  inherited Create;
  FContent := Content;
  FDestination := Destination;
end;

procedure TMySync.DoSynchronize;
begin
  inherited;
  FDestination.Add(FContent);
end;

procedure TaForm.Button1Click(Sender: TObject);
begin
  if not IdTCPClient.Connected then
    IdTCPClient.Connect;
  IdTCPClient.Socket.WriteLn(Edit.Text);
end;

procedure TaForm.FormCreate(Sender: TObject);
const
  // the port which will be used for Server and Client
  C_PORT = 12345;
begin
  IdTCPServer.DefaultPort := C_PORT;
  IdTCPServer.Active := true;
  IdTCPClient.Host := '127.0.0.1';
  IdTCPClient.Port := C_PORT;
end;

procedure TaForm.IdTCPServerExecute(AContext: TIdContext);
begin
  With TMySync.Create(AContext.Connection.Socket.ReadLn, Memo.Lines) do
  begin
    Synchronize;
    Free;
  end;
end;
Share:
22,307
programing delphi
Author by

programing delphi

Updated on July 09, 2022

Comments

  • programing delphi
    programing delphi almost 2 years

    I am using Delphi xe6 to impelement a simple client/server connection. The client form should have a TEdit component and should sent Edit.text string to server memo. I want to use Indy components: TIdTcpServer and TIdTcpClient but I don't know how to setup a simple connection between client and server.

    I would appreciate your help.

  • Remy Lebeau
    Remy Lebeau over 9 years
    TIdTCPServer is a multithreaded component, its OnExecute event is triggered in the context of a worker thread. VCL UI controls are not thread-safe, so you cannot directly access Memo1 like you have shown. Bad things happen when you do that, including crashes, deadlocks, corrupted memory, making TMemo unresponsive to new messages, etc. You must synchronize with the main UI thread, such as with TThread.Synchronize() or TThread.Queue(), or with Indy's TIdSync or TIdNotify classes.
  • linluk
    linluk over 9 years
    @RemyLebeau you are right, this code is not fit for production! it is only designed to demonstrate how TIdTCPServer and TIdTCPClient.
  • Remy Lebeau
    Remy Lebeau over 9 years
    Then you should remove the TMemo portion, it is distracting. Just have the event handler read into a local String variable, and leave use of that variable open.