Revision control

++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
++
++ /*!
++ \example threadedfortuneserver
++ \title Threaded Fortune Server
++ \examplecategory {Networking}
++ \meta tags {tcp,network,threading,server,synchronous-io}
++ \ingroup examples-network
++
++ \brief The Threaded Fortune Server example shows how to create a server for a
++ simple network service that uses threads to handle requests from different
++ clients. It is intended to be run alongside the Fortune Client example.
++
++ \image threadedfortuneserver-example.png {This application creates a server that can a separate thread for each client}
++
++ The implementation of this example is similar to that of the
++ \l{fortuneserver}{Fortune Server} example, but here we will
++ implement a subclass of QTcpServer that starts each connection in a
++ different thread.
++
++ For this we need two classes: FortuneServer, a QTcpServer subclass, and
++ FortuneThread, which inherits QThread.
++
++ \snippet threadedfortuneserver/fortuneserver.h 0
++
++ FortuneServer inherits QTcpServer and reimplements
++ QTcpServer::incomingConnection(). We also use it for storing the list of
++ random fortunes.
++
++ \snippet threadedfortuneserver/fortuneserver.cpp 0
++
++ We use FortuneServer's constructor to simply generate the list of
++ fortunes.
++
++ \snippet threadedfortuneserver/fortuneserver.cpp 1
++
++ Our implementation of QTcpServer::incomingConnection() creates a
++ FortuneThread object, passing the incoming socket descriptor and a random
++ fortune to FortuneThread's constructor. By connecting FortuneThread's
++ finished() signal to QObject::deleteLater(), we ensure that the thread
++ gets deleted once it has finished. We can then call QThread::start(),
++ which starts the thread.
++
++ \snippet threadedfortuneserver/fortunethread.h 0
++
++ Moving on to the FortuneThread class, this is a QThread subclass whose job
++ is to write the fortune to the connected socket. The class reimplements
++ QThread::run(), and it has a signal for reporting errors.
++
++ \snippet threadedfortuneserver/fortunethread.cpp 0
++
++ FortuneThread's constructor simply stores the socket descriptor and
++ fortune text, so that they are available for run() later on.
++
++ \snippet threadedfortuneserver/fortunethread.cpp 1
++
++ The first thing our run() function does is to create a QTcpSocket object
++ on the stack. What's worth noticing is that we are creating this object
++ inside the thread, which automatically associates the socket to the
++ thread's event loop. This ensures that Qt will not try to deliver events
++ to our socket from the main thread while we are accessing it from
++ FortuneThread::run().
++
++ \snippet threadedfortuneserver/fortunethread.cpp 2
++
++ The socket is initialized by calling QTcpSocket::setSocketDescriptor(),
++ passing our socket descriptor as an argument. We expect this to succeed,
++ but just to be sure, (although unlikely, the system may run out of
++ resources,) we catch the return value and report any error.
++
++ \snippet threadedfortuneserver/fortunethread.cpp 3
++
++ As with the \l{fortuneserver}{Fortune Server} example, we encode
++ the fortune into a QByteArray using QDataStream.
++
++ \snippet threadedfortuneserver/fortunethread.cpp 4
++
++ But unlike the previous example, we finish off by calling
++ QTcpSocket::waitForDisconnected(), which blocks the calling thread until
++ the socket has disconnected. Because we are running in a separate thread,
++ the GUI will remain responsive.
++
++ \sa {Fortune Server}, {Fortune Client}, {Blocking Fortune Client}
++ */