doc/src/examples/fortuneclient.qdoc
branchRCL_3
changeset 7 3f74d0d4af4c
equal deleted inserted replaced
6:dee5afe5301f 7:3f74d0d4af4c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the documentation of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 /*!
       
    43     \example network/fortuneclient
       
    44     \title Fortune Client Example
       
    45 
       
    46     The Fortune Client example shows how to create a client for a simple
       
    47     network service using QTcpSocket. It is intended to be run alongside the
       
    48     \l{network/fortuneserver}{Fortune Server} example or
       
    49     the \l{network/threadedfortuneserver}{Threaded Fortune Server} example.
       
    50 
       
    51     \image fortuneclient-example.png Screenshot of the Fortune Client example
       
    52 
       
    53     This example uses a simple QDataStream-based data transfer protocol to
       
    54     request a line of text from a fortune server (from the
       
    55     \l{network/fortuneserver}{Fortune Server} example). The client requests a
       
    56     fortune by simply connecting to the server. The server then responds with
       
    57     a 16-bit (quint16) integer containing the length of the fortune text,
       
    58     followed by a QString.
       
    59 
       
    60     QTcpSocket supports two general approaches to network programming:
       
    61 
       
    62     \list
       
    63 
       
    64     \o \e{The asynchronous (non-blocking) approach.} Operations are scheduled
       
    65     and performed when control returns to Qt's event loop. When the operation
       
    66     is finished, QTcpSocket emits a signal. For example,
       
    67     QTcpSocket::connectToHost() returns immediately, and when the connection
       
    68     has been established, QTcpSocket emits
       
    69     \l{QTcpSocket::connected()}{connected()}.
       
    70 
       
    71     \o \e{The synchronous (blocking) approach.} In non-GUI and multithreaded
       
    72     applications, you can call the \c waitFor...() functions (e.g.,
       
    73     QTcpSocket::waitForConnected()) to suspend the calling thread until the
       
    74     operation has completed, instead of connecting to signals.
       
    75 
       
    76     \endlist
       
    77 
       
    78     In this example, we will demonstrate the asynchronous approach. The
       
    79     \l{network/blockingfortuneclient}{Blocking Fortune Client} example
       
    80     illustrates the synchronous approach.
       
    81 
       
    82     Our class contains some data and a few private slots:
       
    83 
       
    84     \snippet examples/network/fortuneclient/client.h 0
       
    85 
       
    86     Other than the widgets that make up the GUI, the data members include a
       
    87     QTcpSocket pointer, a copy of the fortune text currently displayed, and
       
    88     the size of the packet we are currently reading (more on this later).
       
    89 
       
    90     The socket is initialized in the Client constructor. We'll pass the main
       
    91     widget as parent, so that we won't have to worry about deleting the
       
    92     socket:
       
    93 
       
    94     \snippet examples/network/fortuneclient/client.cpp 0
       
    95     \dots
       
    96     \snippet examples/network/fortuneclient/client.cpp 1
       
    97 
       
    98     The only QTcpSocket signals we need in this example are
       
    99     QTcpSocket::readyRead(), signifying that data has been received, and
       
   100     QTcpSocket::error(), which we will use to catch any connection errors:
       
   101 
       
   102     \dots
       
   103     \snippet examples/network/fortuneclient/client.cpp 3
       
   104     \dots
       
   105     \snippet examples/network/fortuneclient/client.cpp 5
       
   106 
       
   107     Clicking the \gui{Get Fortune} button will invoke the \c
       
   108     requestNewFortune() slot:
       
   109 
       
   110     \snippet examples/network/fortuneclient/client.cpp 6
       
   111 
       
   112     In this slot, we initialize \c blockSize to 0, preparing to read a new block
       
   113     of data.  Because we allow the user to click \gui{Get Fortune} before the
       
   114     previous connection finished closing, we start off by aborting the
       
   115     previous connection by calling QTcpSocket::abort(). (On an unconnected
       
   116     socket, this function does nothing.) We then proceed to connecting to the
       
   117     fortune server by calling QTcpSocket::connectToHost(), passing the
       
   118     hostname and port from the user interface as arguments.
       
   119 
       
   120     As a result of calling \l{QTcpSocket::connectToHost()}{connectToHost()},
       
   121     one of two things can happen:
       
   122 
       
   123     \list
       
   124     \o \e{The connection is established.} In this case, the server will send us a
       
   125     fortune. QTcpSocket will emit \l{QTcpSocket::readyRead()}{readyRead()}
       
   126     every time it receives a block of data.
       
   127 
       
   128     \o \e{An error occurs.} We need to inform the user if the connection
       
   129     failed or was broken. In this case, QTcpSocket will emit
       
   130     \l{QTcpSocket::error()}{error()}, and \c Client::displayError() will be
       
   131     called.
       
   132     \endlist
       
   133 
       
   134     Let's go through the \l{QTcpSocket::error()}{error()} case first:
       
   135 
       
   136     \snippet examples/network/fortuneclient/client.cpp 13
       
   137 
       
   138     We pop up all errors in a dialog using
       
   139     QMessageBox::information(). QTcpSocket::RemoteHostClosedError is silently
       
   140     ignored, because the fortune server protocol ends with the server closing
       
   141     the connection.
       
   142 
       
   143     Now for the \l{QTcpSocket::readyRead()}{readyRead()} alternative. This
       
   144     signal is connected to \c Client::readFortune():
       
   145 
       
   146     \snippet examples/network/fortuneclient/client.cpp 8
       
   147     \codeline
       
   148     \snippet examples/network/fortuneclient/client.cpp 10
       
   149 
       
   150     The protocol is based on QDataStream, so we start by creating a stream
       
   151     object, passing the socket to QDataStream's constructor. We then
       
   152     explicitly set the protocol version of the stream to QDataStream::Qt_4_0
       
   153     to ensure that we're using the same version as the fortune server, no
       
   154     matter which version of Qt the client and server use.
       
   155 
       
   156     Now, TCP is based on sending a stream of data, so we cannot expect to get
       
   157     the entire fortune in one go. Especially on a slow network, the data can
       
   158     be received in several small fragments. QTcpSocket buffers up all incoming
       
   159     data and emits \l{QTcpSocket::readyRead()}{readyRead()} for every new
       
   160     block that arrives, and it is our job to ensure that we have received all
       
   161     the data we need before we start parsing. The server's response starts
       
   162     with the size of the packet, so first we need to ensure that we can read
       
   163     the size, then we will wait until QTcpSocket has received the full packet.
       
   164 
       
   165     \snippet examples/network/fortuneclient/client.cpp 11
       
   166     \codeline
       
   167     \snippet examples/network/fortuneclient/client.cpp 12
       
   168 
       
   169     We proceed by using QDataStream's streaming operator to read the fortune
       
   170     from the socket into a QString. Once read, we can call QLabel::setText()
       
   171     to display the fortune.
       
   172 
       
   173     \sa {Fortune Server Example}, {Blocking Fortune Client Example}
       
   174 */