source: trunk/doc/src/examples/fortuneclient.qdoc@ 1168

Last change on this file since 1168 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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