/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Free Documentation License Usage ** 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. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: http://www.gnu.org/copyleft/fdl.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \example fortuneserver \title Fortune Server Example \ingroup examples-network \brief Demonstrates how to create a server for a network service. This example is intended to be run alongside the \l{fortuneclient}{Fortune Client} example or the \l{blockingfortuneclient}{Blocking Fortune Client} example. \image fortuneserver-example.png Screenshot of the Fortune Server example It 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{fortuneclient}{Fortune Client} example), before closing the connection. \snippet fortuneserver/server.h 0 The server is implemented using a simple class with only one slot, for handling incoming connections. \snippet 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 fortuneserver/server.cpp 2 Our server generates a list of random fortunes that it can send to connecting clients. \snippet 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 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 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 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 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} */