Jump to content
sBsaidus

TidTcpSver hangs while Stopping.

Recommended Posts

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 by sBsaidus

Share this post


Link to post
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 by Remy Lebeau

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×