Socket Programming in C/C++: Handling multiple clients on server without multi threading
This tutorial assumes you have a basic knowledge of socket programming, i.e you are familiar with basic server and client model. In the basic model, server handles only one client at a time, which is a big assumption if you want to develop any scalable server model.
The simple way to handle multiple clients would be to spawn new thread for every new client connected to the server. This method is strongly not recommended because of various disadvantages, namely:
- Threads are difficult to code, debug and sometimes they have unpredictable results.
- Overhead switching of context
- Not scalable for large number of clients
- Deadlocks can occur
A better way to handle multiple clients is by using select() linux command.
- Select command allows to monitor multiple file descriptors, waiting until one of the file descriptors become active.
- For example, if there is some data to be read on one of the sockets select will provide that information.
- Select works like an interrupt handler, which gets activated as soon as any file descriptor sends any data.
Data structure used for select: fd_set
It contains the list of file descriptors to monitor for some activity.
There are four functions associated with fd_set:
fd_set readfds; // Clear an fd_set FD_ZERO(&readfds); // Add a descriptor to an fd_set FD_SET(master_sock, &readfds); // Remove a descriptor from an fd_set FD_CLR(master_sock, &readfds); //If something happened on the master socket , then its an incoming connection FD_ISSET(master_sock, &readfds);
Activating select: Please read the man page for select to check all the arguments for select command.
activity = select( max_fd + 1 , &readfds , NULL , NULL , NULL);
Compile the file and run the server.
Use telnet to connect the server as a client.
Try running on different machines using following command:
telnet localhost 8888
- We have created a fd_set variable readfds, which will monitor all the active file descriptors of the clients plus that of the main server listening socket.
- Whenever a new client will connect, master_socket will be activated and a new fd will be open for that client. We will store its fd in our client_list and in the next iteration we will add it to the readfds to monitor for activity from this client.
- Similarly, if an old client sends some data, readfds will be activated and we will check from the list of existing client to see which client has send the data.
There are other functions that can perform tasks similar to select. pselect , poll , ppoll
This article is contributed by Akshat Sinha. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to email@example.com. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.