How to set up a simple connection between TIdTcpClient and TIdTcpServer to send a string from client to server?
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;
programing delphi
Updated on July 09, 2022Comments
-
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.
-
Ken White over 9 yearsThirty seconds searching here on
[indy] TIdTCPClient
found this post. I'll bet another 30 seconds would find a similar example for Indy's TIdTCPServer. -
bummi over 9 years
-
-
Remy Lebeau over 9 years
TIdTCPServer
is a multithreaded component, itsOnExecute
event is triggered in the context of a worker thread. VCL UI controls are not thread-safe, so you cannot directly accessMemo1
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 withTThread.Synchronize()
orTThread.Queue()
, or with Indy'sTIdSync
orTIdNotify
classes. -
linluk over 9 years@RemyLebeau you are right, this code is not fit for production! it is only designed to demonstrate how
TIdTCPServer
andTIdTCPClient
. -
Remy Lebeau over 9 yearsThen you should remove the
TMemo
portion, it is distracting. Just have the event handler read into a localString
variable, and leave use of that variable open.