2

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.

linluk
  • 1,560
  • 13
  • 31
  • 1
    Thirty seconds searching here on `[indy] TIdTCPClient` found [this post](http://stackoverflow.com/q/22838159). I'll bet another 30 seconds would find a similar example for Indy's TIdTCPServer. – Ken White Oct 29 '14 at 13:39
  • [How to handle received data in the TCPClient ? (Delphi - Indy)](http://stackoverflow.com/questions/5530038/how-to-handle-received-data-in-the-tcpclient-delphi-indy) – bummi Oct 29 '14 at 14:10

2 Answers2

6

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!');
linluk
  • 1,560
  • 13
  • 31
  • 2
    `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. – Remy Lebeau Oct 29 '14 at 16:28
  • @RemyLebeau you are right, this code is not fit for production! it is only designed to demonstrate how `TIdTCPServer` and `TIdTCPClient`. – linluk Oct 29 '14 at 18:34
  • 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. – Remy Lebeau Oct 29 '14 at 18:37
0

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;
bummi
  • 26,435
  • 13
  • 58
  • 97