1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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/fortuneserver
\title Fortune Server Example
\brief The Fortune Server example shows how to create a server for a simple
network service.
The example is intended to be run alongside the
\l{network/fortuneclient}{Fortune Client} example or the
\l{network/blockingfortuneclient}{Blocking Fortune Client} example.
\image fortuneserver-example.png Screenshot of the Fortune Server example
This example uses QTcpServer to accept incoming TCP connections, and a
simple QDataStream based data transfer protocol to write a fortune to the
connecting client (from the \l{network/fortuneclient}{Fortune Client}
example), before closing the connection.
\snippet examples/network/fortuneserver/server.h 0
The server is implemented using a simple class with only one slot, for
handling incoming connections.
\snippet examples/network/fortuneserver/server.cpp 1
In its constructor, our Server object calls QTcpServer::listen() to set up
a QTcpServer to listen on all addresses, on an arbitrary port. In then
displays the port QTcpServer picked in a label, so that user knows which
port the fortune client should connect to.
\snippet examples/network/fortuneserver/server.cpp 2
Our server generates a list of random fortunes that is can send to
connecting clients.
\snippet examples/network/fortuneserver/server.cpp 3
When a client connects to our server, QTcpServer will emit
QTcpServer::newConnection(). In turn, this will invoke our
sendFortune() slot:
\snippet examples/network/fortuneserver/server.cpp 4
The purpose of this slot is to select a random line from our list of
fortunes, encode it into a QByteArray using QDataStream, and then write it
to the connecting socket. This is a common way to transfer binary data
using QTcpSocket. First we create a QByteArray and a QDataStream object,
passing the bytearray to QDataStream's constructor. We then explicitly set
the protocol version of QDataStream to QDataStream::Qt_4_0 to ensure that
we can communicate with clients from future versions of Qt. (See
QDataStream::setVersion().)
\snippet examples/network/fortuneserver/server.cpp 6
At the start of our QByteArray, we reserve space for a 16 bit integer that
will contain the total size of the data block we are sending. We continue
by streaming in a random fortune. Then we seek back to the beginning of
the QByteArray, and overwrite the reserved 16 bit integer value with the
total size of the array. By doing this, we provide a way for clients to
verify how much data they can expect before reading the whole packet.
\snippet examples/network/fortuneserver/server.cpp 7
We then call QTcpServer::newPendingConnection(), which returns the
QTcpSocket representing the server side of the connection. By connecting
QTcpSocket::disconnected() to QObject::deleteLater(), we ensure that the
socket will be deleted after disconnecting.
\snippet examples/network/fortuneserver/server.cpp 8
The encoded fortune is written using QTcpSocket::write(), and we finally
call QTcpSocket::disconnectFromHost(), which will close the connection
after QTcpSocket has finished writing the fortune to the network. Because
QTcpSocket works asynchronously, the data will be written after this
function returns, and control goes back to Qt's event loop. The socket
will then close, which in turn will cause QObject::deleteLater() to delete
it.
\sa {Fortune Client Example}, {Threaded Fortune Server Example}
*/
|