How is QTcpServer really listening for connections
I've been drilling through the source code of the QtCore
and QtNetwork
modules.
Aperantly, QTcpServer
can work in two modes: synchronous and asynchronous.
In synchronous mode after calling listen()
the caller can call waitForNewConnection()
which is a blocking method (the thread will sleep until someone connects to the listening port). This way QTcpServer
can work in a thread without an event loop.
In asynchronous mode QTcpServer
will emit the newConnection()
signal when a new connection was accepted. But to be able to do this there must be an event loop runing. Underlying the QCoreApplication
are the QEventLoop
and QAbstractEventDispatcher
(an abstract class, concrete type is dependent on the OS, for example QEventDispatcherUNIX
). This event dispatcher can monitor for conditions on sockets (represented by file descriptors). It has a method registerSocketNotifier(QSocketNotifier*)
. This method is called by the constructor of the QSocketNotifier
class, which QTcpServer
creates an instance of every time listen()
is called. The only system call that is called when the QTcpServer::listen()
is invoked is, of course, listen()
which just returns immediately, all the real magic happens when the event loop starts running. The event loop (using the dispatcher) will monitor if there is a certain condition on sockets that have been registered. It calls the select()
system call which receives one or more file descriptors to be monitored (by the kernel) for certain conditions (if there is data to be read, if data can be written, or if an error has occurred). The call can block the thread until the conditions on sockets are met, or it can return after some amount of time passes and the conditions on sockets were not met. I am not sure if Qt is calling select()
with a waiting time supplied or without (to block indefinitely), I think it is determined in some complicated way and changeable. So when finally the condition on socket has been met, the event dispatcher will notify the QSocketNotifier
for that socket, which will, in tern, notify the QTcpServer
who is listening to the socket, which will accept the connection, and emit the newConnection()
signal.
So the QTcpServer
does not itself call into the event-loop/socket-monitoring system, but it is dependent upon it via the QSocketNotifier
which it uses for asynchronous recieving of connections.
When synchronous method waitForNewConnection()
is called it just bypasses all the QSocketNotifier
stuff and calls accept()
which blocks the thread until there is an incoming connection.