Question

I am creating a TCP server which receives multiple clients and must be able to send messages to each.

How do I get a handle to the client connection and then send arbitrary data?

Thanks: D

Code:

procedure TFRM_Main.ServerConnect(AContext: TIdContext);
var lAdd: TListItem;
var Index: integer;
begin
  lAdd := ListView.Items.Add;
  //AContext connection ID, what to do here?
  lAdd.Caption := IntToStr(Index);
end;
Was it helpful?

Solution

use:

AContext.Connection.IOHandler.Write( (* bytes *) );
AContext.Connection.IOHandler.WriteFile( (* send a file to the client *) );

For more options, just invoke the code completion(CTRL+SPACE) after IOHandler and see available options, some time ago, I've wrote a simple client/server test app, click here to see and/or download source.

OTHER TIPS

TIdTCPServer is a multithreaded component. Accessing the UI directly from within its OnConnect event (or OnDisconnect, OnExecute, or OnException) is not thread-safe! You need to use Indy's TIdSync or TIdNotify class to access the UI safely.

To answer the original question, the simpliest, but not necessarily the safest, way is to store the TIdContext.Connection object pointer in the TListItem.Data property. The main thread code will then have direct access to the connection when it needs it.

I do not advise that, though. A safer solution is to uniquely identify each client yourself, such as with a username that the client sends, and store that ID in the TIdContext.Data and TListItem.Data properties. Then, when your main thread code wants to send a message to a client, it can loop through the TIdTCPServer.Contexts list looking for the desired ID, and if found then it will have access to the corresponding TIdContext.Connection object.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top