summaryrefslogtreecommitdiffstats
path: root/doc/src/examples/blockingfortuneclient.qdoc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src/examples/blockingfortuneclient.qdoc')
-rw-r--r--doc/src/examples/blockingfortuneclient.qdoc216
1 files changed, 0 insertions, 216 deletions
diff --git a/doc/src/examples/blockingfortuneclient.qdoc b/doc/src/examples/blockingfortuneclient.qdoc
deleted file mode 100644
index 6c3be78859..0000000000
--- a/doc/src/examples/blockingfortuneclient.qdoc
+++ /dev/null
@@ -1,216 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** GNU Free Documentation License
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms
-** and conditions contained in a signed written agreement between you
-** and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \example network/blockingfortuneclient
- \title Blocking Fortune Client Example
-
- The Blocking Fortune Client example shows how to create a client for a
- network service using QTcpSocket's synchronous API in a non-GUI thread.
-
- \image blockingfortuneclient-example.png
-
- QTcpSocket supports two general approaches to network programming:
-
- \list
-
- \li \e{The asynchronous (non-blocking) approach.} Operations are scheduled
- and performed when control returns to Qt's event loop. When the operation
- is finished, QTcpSocket emits a signal. For example,
- QTcpSocket::connectToHost() returns immediately, and when the connection
- has been established, QTcpSocket emits
- \l{QTcpSocket::connected()}{connected()}.
-
- \li \e{The synchronous (blocking) approach.} In non-GUI and multithreaded
- applications, you can call the \c waitFor...() functions (e.g.,
- QTcpSocket::waitForConnected()) to suspend the calling thread until the
- operation has completed, instead of connecting to signals.
-
- \endlist
-
- The implementation is very similar to the
- \l{network/fortuneclient}{Fortune Client} example, but instead of having
- QTcpSocket as a member of the main class, doing asynchronous networking in
- the main thread, we will do all network operations in a separate thread
- and use QTcpSocket's blocking API.
-
- The purpose of this example is to demonstrate a pattern that you can use
- to simplify your networking code, without losing responsiveness in your
- user interface. Use of Qt's blocking network API often leads to
- simpler code, but because of its blocking behavior, it should only be used
- in non-GUI threads to prevent the user interface from freezing. But
- contrary to what many think, using threads with QThread does not
- necessarily add unmanagable complexity to your application.
-
- We will start with the FortuneThread class, which handles the network
- code.
-
- \snippet examples/network/blockingfortuneclient/fortunethread.h 0
-
- FortuneThread is a QThread subclass that provides an API for scheduling
- requests for fortunes, and it has signals for delivering fortunes and
- reporting errors. You can call requestNewFortune() to request a new
- fortune, and the result is delivered by the newFortune() signal. If any
- error occurs, the error() signal is emitted.
-
- It's important to notice that requestNewFortune() is called from the main,
- GUI thread, but the host name and port values it stores will be accessed
- from FortuneThread's thread. Because we will be reading and writing
- FortuneThread's data members from different threads concurrently, we use
- QMutex to synchronize access.
-
- \snippet examples/network/blockingfortuneclient/fortunethread.cpp 2
-
- The requestNewFortune() function stores the host name and port of the
- fortune server as member data, and we lock the mutex with QMutexLocker to
- protect this data. We then start the thread, unless it is already
- running. We will come back to the QWaitCondition::wakeOne() call later.
-
- \snippet examples/network/blockingfortuneclient/fortunethread.cpp 4
- \snippet examples/network/blockingfortuneclient/fortunethread.cpp 5
-
- In the run() function, we start by acquiring the mutex lock, fetching the
- host name and port from the member data, and then releasing the lock
- again. The case that we are protecting ourselves against is that \c
- requestNewFortune() could be called at the same time as we are fetching
- this data. QString is \l reentrant but \e not \l{thread-safe}, and we must
- also avoid the unlikely risk of reading the host name from one request,
- and port of another. And as you might have guessed, FortuneThread can only
- handle one request at a time.
-
- The run() function now enters a loop:
-
- \snippet examples/network/blockingfortuneclient/fortunethread.cpp 6
-
- The loop will continue requesting fortunes for as long as \e quit is
- false. We start our first request by creating a QTcpSocket on the stack,
- and then we call \l{QTcpSocket::connectToHost()}{connectToHost()}. This
- starts an asynchronous operation which, after control returns to Qt's
- event loop, will cause QTcpSocket to emit
- \l{QTcpSocket::connected()}{connected()} or
- \l{QTcpSocket::error()}{error()}.
-
- \snippet examples/network/blockingfortuneclient/fortunethread.cpp 8
-
- But since we are running in a non-GUI thread, we do not have to worry
- about blocking the user interface. So instead of entering an event loop,
- we simply call QTcpSocket::waitForConnected(). This function will wait,
- blocking the calling thread, until QTcpSocket emits connected() or an
- error occurs. If connected() is emitted, the function returns true; if the
- connection failed or timed out (which in this example happens after 5
- seconds), false is returned. QTcpSocket::waitForConnected(), like the
- other \c waitFor...() functions, is part of QTcpSocket's \e{blocking
- API}.
-
- After this statement, we have a connected socket to work with. Now it's
- time to see what the fortune server has sent us.
-
- \snippet examples/network/blockingfortuneclient/fortunethread.cpp 9
- \snippet examples/network/blockingfortuneclient/fortunethread.cpp 10
-
- This step is to read the size of the packet. Although we are only reading
- two bytes here, and the \c while loop may seem to overdo it, we present this
- code to demonstrate a good pattern for waiting for data using
- QTcpSocket::waitForReadyRead(). It goes like this: For as long as we still
- need more data, we call waitForReadyRead(). If it returns false,
- we abort the operation. After this statement, we know that we have received
- enough data.
-
- \snippet examples/network/blockingfortuneclient/fortunethread.cpp 11
-
- Now we can create a QDataStream object, passing the socket to
- QDataStream's constructor, and as in the other client examples we set
- the stream protocol version to QDataStream::Qt_4_0, and read the size
- of the packet.
-
- \snippet examples/network/blockingfortuneclient/fortunethread.cpp 12
- \snippet examples/network/blockingfortuneclient/fortunethread.cpp 13
-
- Again, we'll use a loop that waits for more data by calling
- QTcpSocket::waitForReadyRead(). In this loop, we're waiting until
- QTcpSocket::bytesAvailable() returns the full packet size.
-
- \snippet examples/network/blockingfortuneclient/fortunethread.cpp 14
-
- Now that we have all the data that we need, we can use QDataStream to
- read the fortune string from the packet. The resulting fortune is
- delivered by emitting newFortune().
-
- \snippet examples/network/blockingfortuneclient/fortunethread.cpp 15
-
- The final part of our loop is that we acquire the mutex so that we can
- safely read from our member data. We then let the thread go to sleep by
- calling QWaitCondition::wait(). At this point, we can go back to
- requestNewFortune() and look closed at the call to wakeOne():
-
- \snippet examples/network/blockingfortuneclient/fortunethread.cpp 1
- \dots
- \snippet examples/network/blockingfortuneclient/fortunethread.cpp 3
-
- What happened here was that because the thread falls asleep waiting for a
- new request, we needed to wake it up again when a new request
- arrives. QWaitCondition is often used in threads to signal a wakeup call
- like this.
-
- \snippet examples/network/blockingfortuneclient/fortunethread.cpp 0
-
- Finishing off the FortuneThread walkthrough, this is the destructor that
- sets \e quit to true, wakes up the thread and waits for the thread to exit
- before returning. This lets the \c while loop in run() will finish its current
- iteration. When run() returns, the thread will terminate and be destroyed.
-
- Now for the BlockingClient class:
-
- \snippet examples/network/blockingfortuneclient/blockingclient.h 0
-
- BlockingClient is very similar to the Client class in the
- \l{network/fortuneclient}{Fortune Client} example, but in this class
- we store a FortuneThread member instead of a pointer to a QTcpSocket.
- When the user clicks the "Get Fortune" button, the same slot is called,
- but its implementation is slightly different:
-
- \snippet examples/network/blockingfortuneclient/blockingclient.cpp 0
- \snippet examples/network/blockingfortuneclient/blockingclient.cpp 1
-
- We connect our FortuneThread's two signals newFortune() and error() (which
- are somewhat similar to QTcpSocket::readyRead() and QTcpSocket::error() in
- the previous example) to requestNewFortune() and displayError().
-
- \snippet examples/network/blockingfortuneclient/blockingclient.cpp 2
-
- The requestNewFortune() slot calls FortuneThread::requestNewFortune(),
- which \e shedules the request. When the thread has received a new fortune
- and emits newFortune(), our showFortune() slot is called:
-
- \snippet examples/network/blockingfortuneclient/blockingclient.cpp 3
- \codeline
- \snippet examples/network/blockingfortuneclient/blockingclient.cpp 4
-
- Here, we simply display the fortune we received as the argument.
-
- \sa {Fortune Client Example}, {Fortune Server Example}
-*/