Viadeo Twitter Google Bookmarks ! Facebook Digg del.icio.us MySpace Yahoo MyWeb Blinklist Netvouz Reddit Simpy StumbleUpon Bookmarks Windows Live Favorites 
Logo Documentation Qt ·  Page d'accueil  ·  Toutes les classes  ·  Classes principales  ·  Annotées  ·  Classes groupées  ·  Modules  ·  Fonctions  · 

Threaded Fortune Server Example

Files:

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.

The implementation of this example is similar to that of the 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.

    class FortuneServer : public QTcpServer
    {
        Q_OBJECT

    public:
        FortuneServer(QObject *parent = 0);

    protected:
        void incomingConnection(int socketDescriptor);

    private:
        QStringList fortunes;
    };

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

    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.

    void FortuneServer::incomingConnection(int socketDescriptor)
    {
        QString fortune = fortunes.at(rand() % fortunes.size());
        FortuneThread *thread = new FortuneThread(socketDescriptor, fortune, this);
        connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
        thread->start();
    }

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.

    class FortuneThread : public QThread
    {
        Q_OBJECT

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

        void run();

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

    private:
        int socketDescriptor;
        QString text;
    };

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.

    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.

    void FortuneThread::run()
    {
        QTcpSocket tcpSocket;

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().

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

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.

        QByteArray block;
        QDataStream out(&block, QIODevice::WriteOnly);
        out.setVersion(QDataStream::Qt_4_0);
        out << (quint16)0;
        out << text;
        out.device()->seek(0);
        out << (quint16)(block.size() - sizeof(quint16));

As with the Fortune Server example, we encode the fortune into a QByteArray using QDataStream.

        tcpSocket.write(block);
        tcpSocket.disconnectFromHost();
        tcpSocket.waitForDisconnected();
    }

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.

See also Fortune Server Example, Fortune Client Example, and Blocking Fortune Client Example.

Publicité

Best Of

Actualités les plus lues

Semaine
Mois
Année
  1. « Quelque chose ne va vraiment pas avec les développeurs "modernes" », un développeur à "l'ancienne" critique la multiplication des bibliothèques 77
  2. Apercevoir la troisième dimension ou l'utilisation multithreadée d'OpenGL dans Qt, un article des Qt Quarterly traduit par Guillaume Belz 0
  3. Les développeurs ignorent-ils trop les failles découvertes dans leur code ? Prenez-vous en compte les remarques des autres ? 17
  4. BlackBerry 10 : premières images du prochain OS de RIM qui devrait intégrer des widgets et des tuiles inspirées de Windows Phone 0
  5. Quelles nouveautés de C++11 Visual C++ doit-il rapidement intégrer ? Donnez-nous votre avis 10
  6. Adieu qmake, bienvenue qbs : Qt Building Suite, un outil déclaratif et extensible pour la compilation de projets Qt 17
  7. 2017 : un quinquennat pour une nouvelle version du C++ ? Possible, selon Herb Sutter 6
Page suivante

Le blog Digia au hasard

Logo

Créer des applications avec un style Metro avec Qt, exemples en QML et C++, un article de Digia Qt traduit par Thibaut Cuvelier

Le blog Digia est l'endroit privilégié pour la communication sur l'édition commerciale de Qt, où des réponses publiques sont apportées aux questions les plus posées au support. Lire l'article.

Communauté

Ressources

Liens utiles

Contact

  • Vous souhaitez rejoindre la rédaction ou proposer un tutoriel, une traduction, une question... ? Postez dans le forum Contribuez ou contactez-nous par MP ou par email (voir en bas de page).

Qt dans le magazine

Cette page est une traduction d'une page de la documentation de Qt, écrite par Nokia Corporation and/or its subsidiary(-ies). Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia. Qt 4.1
Copyright © 2012 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon, vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
Vous avez déniché une erreur ? Un bug ? Une redirection cassée ? Ou tout autre problème, quel qu'il soit ? Ou bien vous désirez participer à ce projet de traduction ? N'hésitez pas à nous contacter ou par MP !
 
 
 
 
Partenaires

Hébergement Web