sBsaidus 0 Posted September 25, 2023 (edited) Hello. In the attached zip, a very simple usage for IdTcpServer and IdTcpClient. What I want to do is notify all connected client to disconnect while closing Server application or juste send a 'QUIT' command to all of connected clients while stop listening. But I encounter many problems. Can someone tel me what's wrong with the code. Thank you. CS.zip Edited September 25, 2023 by sBsaidus Share this post Link to post
Remy Lebeau 1396 Posted September 25, 2023 (edited) 11 hours ago, sBsaidus said: Can someone tel me what's wrong with the code. There is quite a lot wrong with the server code you have shown. TIdTCPServer is a multi-threaded component. The listening ports are managed in worker threads. Each connected client is handled in its own worker thread. Your management of your f_CClients list is not thread-safe, or even accurate in places. It is also redundant, as TIdTCPServer already has a thread-safe list of connected clients in its Contexts property. You should just get rid of your f_CClients list altogether and use the Contexts list by itself. You can store your tCClient objects in the TIdContext.Data property, or you can derive it from TIdServerContext and then set it to the TIdTCPServer.ContextClass property before activating the server. You are accessing your TMemo and TListView directly in the context of each client worker thread. Any access to the UI from a worker thread must be synchronized with the main UI thread, which you are not doing at all. Use TThread.Synchronize() or TThread.Queue() (or Indy's TIdSync or TIdNotify) for that purpose. Do be careful with TThread.Synchronize()/TIdSync, though. Since they are synchronous, if you deactivate the server in the main UI thread, and then try to sync with the UI thread, you will deadlock the server. So, don't sync synchronously while deactivating the server, or do the deactivation in a separate thread so the main UI thread remains free to process sync requests. You are directly sending your QUIT commands to clients from the context of the main UI thread. In this example, you are not sending anything else to the clients, but if you were, you would potentially be overlapping any sends those clients' threads may happen to be performing at the same time, which would corrupt your communications. You must serialize access to a client's socket when sending to it across thread boundaries. It is generally best to keep your socket I/O with a given client in that client's worker thread as much as possible. In short, your server code needs a good amount of rewriting to operate safely in a multi-threaded environment. Edited September 25, 2023 by Remy Lebeau Share this post Link to post
sBsaidus 0 Posted September 25, 2023 Thank you @Remy Lebeau, I'll try to follow your advises and give a feedback. Thank you. Share this post Link to post