Hi I am writing server on linux in C language using TCP.
The server has to handle multiple connections (up to 5000 approximately). 5000 is max, but average should be about 500 - 1000.
I would like to know what is better to use for handling the clients connections and listening. If is better to use one thread for everyone client or use select()
function.
1) Thread - every client has his own thread. The thread is listening for client's request and process it.
Select function - one loop with select, where all requests are processing. (something similar to this http://www.binarytides.com/multiple-socket-connections-fdset-select-linux/)
If I would use threads, it would need lot of memory and cpu performance. Therefore, I prefer to use select but I am not sure if select can handle so many connections and if it won't slow down responses from server (there is the loop which has to go through the clients sockets ). So is it OK to use select for so many clients ?
I was looking for my answer but, I haven't found it, or I just don't know what to search. So please don't be upset.
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.
The server can receive any number of connections on its single listening port, as long as a different address/port combination is used by each client.
A single listening port can accept more than one connection simultaneously. There is a '64K' limit that is often cited, but that is per client per server port, and needs clarifying.
It is possible for a client to request a specific TCP port to connect from using the bind() system call; however, if two clients request the same port, only the first request will succeed.
In general, threads are quite costly: each thread wants its call stack (typically megabytes) and consume a task in the scheduler. So the common advice is to have a few dozen threads at most (perhaps using some thread pool). Probably a hundred threads could be reasonable (on some powerful server), but many thousands threads probably won't be reasonable: even idle threads are somehow expensive.
So I would recommend using a multiplexing call like poll(2) (better than select
which usually has a hard-coded limit on the number of file descriptors, the builtin size of fd_set
). You might use in addition a thread pool to serve active connections (or requests).
Actually, what you refer to is called the C10K problem. You could also use epoll(7).
Several event loop libraries are providing some useful infrastructure: libev, libevent, Glib from GTK, ...
BTW, you could have a mixed approach: a pool of processes (perhaps running on different machines) using thread pools.
Notice that some compilers offer split stacks, and the goroutines of the Go language are designed to enable many "green threads".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With