IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Threaded Fortune Server Example

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.

Article lu   fois.

L'auteur

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

Threaded Fortune Server Example▲

Image non disponible

The implementation of this example is similar to that of the https:// example, but here we will implement a subclass of https:// that starts each connection in a different thread.

For this we need two classes: FortuneServer, a https:// subclass, and FortuneThread, which inherits https://.

 
Sélectionnez
class FortuneServer : public QTcpServer
{
    Q_OBJECT

public:
    FortuneServer(QObject *parent = 0);

protected:
    void incomingConnection(qintptr socketDescriptor) override;

private:
    QStringList fortunes;
};

FortuneServer inherits https:// and reimplements https://(). We also use it for storing the list of random fortunes.

 
Sélectionnez
FortuneServer::FortuneServer(QObject *parent)
    : QTcpServer(parent)
{
    fortunes << tr("You've been leading a dog's life. Stay off the furniture.")
             << tr("You've got to think about tomorrow.")
             << tr("You will be surprised by a loud noise.")
             << tr("You will feel hungry again in another hour.")
             << tr("You might have mail.")
             << tr("You cannot kill time without injuring eternity.")
             << tr("Computers are not intelligent. They only think they are.");
}

We use FortuneServer's constructor to simply generate the list of fortunes.

 
Sélectionnez
void FortuneServer::incomingConnection(qintptr socketDescriptor)
{
    QString fortune = fortunes.at(QRandomGenerator::global()->bounded(fortunes.size()));
    FortuneThread *thread = new FortuneThread(socketDescriptor, fortune, this);
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    thread->start();
}

Our implementation of https://() creates a FortuneThread object, passing the incoming socket descriptor and a random fortune to FortuneThread's constructor. By connecting FortuneThread's finished() signal to https://(), we ensure that the thread gets deleted once it has finished. We can then call https://(), which starts the thread.

 
Sélectionnez
class FortuneThread : public QThread
{
    Q_OBJECT

public:
    FortuneThread(int socketDescriptor, const QString &fortune, QObject *parent);

    void run() override;

signals:
    void error(QTcpSocket::SocketError socketError);

private:
    int socketDescriptor;
    QString text;
};

Moving on to the FortuneThread class, this is a https:// subclass whose job is to write the fortune to the connected socket. The class reimplements https://(), and it has a signal for reporting errors.

 
Sélectionnez
FortuneThread::FortuneThread(int socketDescriptor, const QString &fortune, QObject *parent)
    : QThread(parent), socketDescriptor(socketDescriptor), text(fortune)
{
}

FortuneThread's constructor simply stores the socket descriptor and fortune text, so that they are available for run() later on.

 
Sélectionnez
void FortuneThread::run()
{
    QTcpSocket tcpSocket;

The first thing our run() function does is to create a https:// 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().

 
Sélectionnez
    if (!tcpSocket.setSocketDescriptor(socketDescriptor)) {
        emit error(tcpSocket.error());
        return;
    }

The socket is initialized by calling https://(), 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.

 
Sélectionnez
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_0);
    out << text;

As with the https:// example, we encode the fortune into a https:// using https://.

 
Sélectionnez
    tcpSocket.write(block);
    tcpSocket.disconnectFromHost();
    tcpSocket.waitForDisconnected();
}

But unlike the previous example, we finish off by calling https://(), which blocks the calling thread until the socket has disconnected. Because we are running in a separate thread, the GUI will remain responsive.

List of Files▲

Files:

List of Files▲

  • threadedfortuneserver/dialog.cpp

  • threadedfortuneserver/dialog.h

  • threadedfortuneserver/fortuneserver.cpp

  • threadedfortuneserver/fortuneserver.h

  • threadedfortuneserver/fortunethread.cpp

  • threadedfortuneserver/fortunethread.h

  • threadedfortuneserver/main.cpp

  • threadedfortuneserver/threadedfortuneserver.pro

See Also▲

See also https://, https://, https://

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Ce document est disponible sous la licence https:// telle que publiée par la Free Software Foundation.