How to store an identifier in a ListView a client connection - Indy 10
-
27-10-2019 - |
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;
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.