Michał Ziobro
Michał Ziobro

Reputation: 11762

Multithreaded TCP server on background thread- how to force close from main thread

I have GUI application this application starts server by calling start_server() function. Then there is created TCP passive socket receiving incoming connections in the server loop(we have connection sockets here) and handling them on multiple threads simultaneously.

Now I need some end_server() function that force server and all connections to close. What is the best practice to close such servers.

I consider doing this in such way:

  1. pass to start_server() function some server_info_t structure.
  2. then when passive socket is created its descriptor i stored in server_info_t, there is also stored its binding port number
  3. in server_info_t structure there is on_server_start callback that is called asynchronously after server has been created correctly returning some information about created server like port number on which server is listening (this enable to change GUI controls like status icon from red to green)
  4. then i pass the same structure server_info_t info server_loop and there where new connection from client is coming I will take the connection socket and store its descriptor inside server_info_t structure some linked_list_t or hash_map_t of connection sockets.
  5. now i can invoke some asynchronous callback like on_client_connected and pass handling of connection (connection socket) to another function (separate thread from thread pool), and then server loop waits for next connection. I also need to pass server_info_t structure here to remove connection_socket descriptor from linked_list of conn socket descriptors it connection handling for given client finish.
  6. Here inside struct server_info there can be another callback function on_client_disconnected
  7. Now outside this multithreaded server running in the background I have a GUI app that started the server, and it has the pointer to server_info_t structure that stores all information about server: port number, passive socket, linked_list of actually connected connection sockets (active sockets), callback functions pointers that should be called to inform about server events, etc. So I think I could then make end_server(server_info_t) (ex. when user clicks STOP in GUI application user interface) and heres the magic happens... server stops. But how?

Should I take all connection sockets (while iteration over linked list in server_info_t structure) and close them using (shutdown + close), and then shutdown + close passive socket?

Then I could even call some callback on_server_end which pointer I found in server_info_t structure.

Should I use some mutex to synchronise access to this server_info_t structure?

Upvotes: 0

Views: 459

Answers (1)

Dmitry Poroh
Dmitry Poroh

Reputation: 3825

Should I use some mutex to synchronise access to this server_info_t structure?

You definitely should synchronize access to the shared data structure.

Should I take all connection sockets (while iteration over linked list in server_info_t structure) and close them using (shutdown + close), and then shutdown + close passive socket?

This is kind of quick and dirty solution. Better design is to inform worker thread the connection should be closed. In this case you can:

  • Inform clients of the server about reason of the connection shutdown
  • Complete process of current request

Way to solve "inform" task can be different:

  • If you use select/poll/epoll methods you can use designated socket (for ex. socketpair) to indicate stop
  • If you use blocking calls you can use pthread_cancel mechanisms but they are very system-dependent
  • If your worker thread wakeups periodically you can use kind of atomic flag

Upvotes: 1

Related Questions