<?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <!-- /tmp/qt-4.2.1-harald-1161357942206/qt-x11-opensource-src-4.2.1/doc/src/examples/fortuneserver.qdoc --> <head> <title>Qt 4.2: Fortune Server Example</title> <link href="classic.css" rel="stylesheet" type="text/css" /> </head> <body> <table border="0" cellpadding="0" cellspacing="0" width="100%"> <tr> <td align="left" valign="top" width="32"><a href="http://www.trolltech.com/products/qt"><img src="images/qt-logo.png" align="left" width="32" height="32" border="0" /></a></td> <td width="1"> </td><td class="postheader" valign="center"><a href="index.html"><font color="#004faf">Home</font></a> · <a href="classes.html"><font color="#004faf">All Classes</font></a> · <a href="mainclasses.html"><font color="#004faf">Main Classes</font></a> · <a href="groups.html"><font color="#004faf">Grouped Classes</font></a> · <a href="modules.html"><font color="#004faf">Modules</font></a> · <a href="functions.html"><font color="#004faf">Functions</font></a></td> <td align="right" valign="top" width="230"><a href="http://www.trolltech.com"><img src="images/trolltech-logo.png" align="right" width="203" height="32" border="0" /></a></td></tr></table><h1 align="center">Fortune Server Example<br /><small></small></h1> <p>Files:</p> <ul> <li><a href="network-fortuneserver-server-cpp.html">network/fortuneserver/server.cpp</a></li> <li><a href="network-fortuneserver-server-h.html">network/fortuneserver/server.h</a></li> <li><a href="network-fortuneserver-main-cpp.html">network/fortuneserver/main.cpp</a></li> </ul> <p>The Fortune Server example shows how to create a server for a simple network service. It is intended to be run alongside the <a href="network-fortuneclient.html">Fortune Client</a> example or the the <a href="network-blockingfortuneclient.html">Blocking Fortune Client</a> example.</p> <p align="center"><img src="images/fortuneserver-example.png" alt="Screenshot of the Fortune Server example" /></p><p>This example uses <a href="qtcpserver.html">QTcpServer</a> to accept incoming TCP connections, and a simple <a href="qdatastream.html">QDataStream</a> based data transfer protocol to write a fortune to the connecting client (from the <a href="network-fortuneclient.html">Fortune Client</a> example), before closing the connection.</p> <pre> class Server : public QDialog { Q_OBJECT public: Server(QWidget *parent = 0); private slots: void sendFortune(); private: QLabel *statusLabel; QPushButton *quitButton; QTcpServer *tcpServer; QStringList fortunes; };</pre> <p>The server is implemented using a simple class with only one slot, for handling incoming connections.</p> <pre> tcpServer = new QTcpServer(this); if (!tcpServer->listen()) { QMessageBox::critical(this, tr("Fortune Server"), tr("Unable to start the server: %1.") .arg(tcpServer->errorString())); close(); return; } statusLabel->setText(tr("The server is running on port %1.\n" "Run the Fortune Client example now.") .arg(tcpServer->serverPort()));</pre> <p>In its constructor, our Server object calls <a href="qtcpserver.html#listen">QTcpServer::listen</a>() to set up a <a href="qtcpserver.html">QTcpServer</a> to listen on all addresses, on an arbitrary port. In then displays the port <a href="qtcpserver.html">QTcpServer</a> picked in a label, so that user knows which port the fortune client should connect to.</p> <pre> fortunes << tr("You've been leading a dog's life. Stay off the furniture.") << tr("You've got to think about tomorrow.") << tr("You will be surprised by a loud noise.") << tr("You will feel hungry again in another hour.") << tr("You might have mail.") << tr("You cannot kill time without injuring eternity.") << tr("Computers are not intelligent. They only think they are.");</pre> <p>Our server generates a list of random fortunes that is can send to connecting clients.</p> <pre> connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendFortune()));</pre> <p>When a client connects to our server, <a href="qtcpserver.html">QTcpServer</a> will emit <a href="qtcpserver.html#newConnection">QTcpServer::newConnection</a>(). In turn, this will invoke our sendFortune() slot:</p> <pre> void Server::sendFortune() { QByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_4_0);</pre> <p>The purpose of this slot is to select a random line from our list of fortunes, encode it into a <a href="qbytearray.html">QByteArray</a> using <a href="qdatastream.html">QDataStream</a>, and then write it to the connecting socket. This is a common way to transfer binary data using <a href="qtcpsocket.html">QTcpSocket</a>. First we create a <a href="qbytearray.html">QByteArray</a> and a <a href="qdatastream.html">QDataStream</a> object, passing the bytearray to <a href="qdatastream.html">QDataStream</a>'s constructor. We then explicitly set the protocol version of <a href="qdatastream.html">QDataStream</a> to <a href="qdatastream.html#Version-enum">QDataStream::Qt_4_0</a> to ensure that we can communicate with clients from future versions of Qt. (See <a href="qdatastream.html#setVersion">QDataStream::setVersion</a>().)</p> <pre> out << (quint16)0; out << fortunes.at(qrand() % fortunes.size()); out.device()->seek(0); out << (quint16)(block.size() - sizeof(quint16));</pre> <p>At the start of our <a href="qbytearray.html">QByteArray</a>, 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 <a href="qbytearray.html">QByteArray</a>, 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.</p> <pre> QTcpSocket *clientConnection = tcpServer->nextPendingConnection(); connect(clientConnection, SIGNAL(disconnected()), clientConnection, SLOT(deleteLater()));</pre> <p>We then call QTcpServer::newPendingConnection(), which returns the <a href="qtcpsocket.html">QTcpSocket</a> representing the server side of the connection. By connecting <a href="qabstractsocket.html#disconnected">QTcpSocket::disconnected</a>() to <a href="qobject.html#deleteLater">QObject::deleteLater</a>(), we ensure that the socket will be deleted after disconnecting.</p> <pre> clientConnection->write(block); clientConnection->disconnectFromHost(); }</pre> <p>The encoded fortune is written using <a href="qiodevice.html#write">QTcpSocket::write</a>(), and we finally call <a href="qabstractsocket.html#disconnectFromHost">QTcpSocket::disconnectFromHost</a>(), which will close the connection after <a href="qtcpsocket.html">QTcpSocket</a> has finished writing the fortune to the network. Because <a href="qtcpsocket.html">QTcpSocket</a> 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 <a href="qobject.html#deleteLater">QObject::deleteLater</a>() to delete it.</p> <p>See also <a href="network-fortuneclient.html">Fortune Client Example</a> and <a href="network-threadedfortuneserver.html">Threaded Fortune Server Example</a>.</p> <p /><address><hr /><div align="center"> <table width="100%" cellspacing="0" border="0"><tr class="address"> <td width="30%">Copyright © 2006 <a href="trolltech.html">Trolltech</a></td> <td width="40%" align="center"><a href="trademarks.html">Trademarks</a></td> <td width="30%" align="right"><div align="right">Qt 4.2.1</div></td> </tr></table></div></address></body> </html>