File: network-fortuneserver.html

package info (click to toggle)
qt4-x11 4%3A4.8.2%2Bdfsg-11
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 701,696 kB
  • sloc: cpp: 2,686,179; ansic: 375,485; python: 25,859; sh: 19,349; xml: 17,091; perl: 14,765; yacc: 5,383; asm: 5,038; makefile: 1,259; lex: 555; ruby: 526; objc: 347; cs: 112; pascal: 112; php: 54; sed: 34
file content (139 lines) | stat: -rw-r--r-- 14,818 bytes parent folder | download
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en_US" lang="en_US">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- fortuneserver.qdoc -->
  <title>Qt 4.8: Fortune Server Example</title>
  <link rel="stylesheet" type="text/css" href="style/offline.css" />
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="content"> 
    <a href="index.html" class="qtref"><span>Qt Reference Documentation</span></a>
  </div>
  <div class="breadcrumb toolblock">
    <ul>
      <li class="first"><a href="index.html">Home</a></li>
      <!--  Breadcrumbs go here -->
<li><a href="all-examples.html">Examples</a></li>
<li>Fortune Server Example</li>
    </ul>
  </div>
</div>
<div class="content mainContent">
<h1 class="title">Fortune Server Example</h1>
<span class="subtitle"></span>
<!-- $$$network/fortuneserver-description -->
<div class="descr"> <a name="details"></a>
<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>
<li><a href="network-fortuneserver-fortuneserver-pro.html">network/fortuneserver/fortuneserver.pro</a></li>
</ul>
<p>The Fortune Server example shows how to create a server for a simple network service.<p>The example is intended to be run alongside the <a href="network-fortuneclient.html">Fortune Client</a> example or the <a href="network-blockingfortuneclient.html">Blocking Fortune Client</a> example.</p>
<p class="centerAlign"><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="cpp"> <span class="keyword">class</span> Server : <span class="keyword">public</span> <span class="type"><a href="qdialog.html">QDialog</a></span>
 {
     Q_OBJECT

 <span class="keyword">public</span>:
     Server(<span class="type"><a href="qwidget.html">QWidget</a></span> <span class="operator">*</span>parent <span class="operator">=</span> <span class="number">0</span>);

 <span class="keyword">private</span> <span class="keyword">slots</span>:
     <span class="type">void</span> sessionOpened();
     <span class="type">void</span> sendFortune();

 <span class="keyword">private</span>:
     <span class="type"><a href="qlabel.html">QLabel</a></span> <span class="operator">*</span>statusLabel;
     <span class="type"><a href="qpushbutton.html">QPushButton</a></span> <span class="operator">*</span>quitButton;
     <span class="type"><a href="qtcpserver.html">QTcpServer</a></span> <span class="operator">*</span>tcpServer;
     <span class="type"><a href="qstringlist.html">QStringList</a></span> fortunes;
     <span class="type"><a href="qnetworksession.html">QNetworkSession</a></span> <span class="operator">*</span>networkSession;
 };</pre>
<p>The server is implemented using a simple class with only one slot, for handling incoming connections.</p>
<pre class="cpp">     tcpServer <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qtcpserver.html">QTcpServer</a></span>(<span class="keyword">this</span>);
     <span class="keyword">if</span> (<span class="operator">!</span>tcpServer<span class="operator">-</span><span class="operator">&gt;</span>listen()) {
         <span class="type"><a href="qmessagebox.html">QMessageBox</a></span><span class="operator">::</span>critical(<span class="keyword">this</span><span class="operator">,</span> tr(<span class="string">&quot;Fortune Server&quot;</span>)<span class="operator">,</span>
                               tr(<span class="string">&quot;Unable to start the server: %1.&quot;</span>)
                               <span class="operator">.</span>arg(tcpServer<span class="operator">-</span><span class="operator">&gt;</span>errorString()));
         close();
         <span class="keyword">return</span>;
     }
     <span class="type"><a href="qstring.html">QString</a></span> ipAddress;
     <span class="type"><a href="qlist.html">QList</a></span><span class="operator">&lt;</span><span class="type"><a href="qhostaddress.html">QHostAddress</a></span><span class="operator">&gt;</span> ipAddressesList <span class="operator">=</span> <span class="type"><a href="qnetworkinterface.html">QNetworkInterface</a></span><span class="operator">::</span>allAddresses();
     <span class="comment">// use the first non-localhost IPv4 address</span>
     <span class="keyword">for</span> (<span class="type">int</span> i <span class="operator">=</span> <span class="number">0</span>; i <span class="operator">&lt;</span> ipAddressesList<span class="operator">.</span>size(); <span class="operator">+</span><span class="operator">+</span>i) {
         <span class="keyword">if</span> (ipAddressesList<span class="operator">.</span>at(i) <span class="operator">!</span><span class="operator">=</span> <span class="type"><a href="qhostaddress.html">QHostAddress</a></span><span class="operator">::</span>LocalHost <span class="operator">&amp;</span><span class="operator">&amp;</span>
             ipAddressesList<span class="operator">.</span>at(i)<span class="operator">.</span>toIPv4Address()) {
             ipAddress <span class="operator">=</span> ipAddressesList<span class="operator">.</span>at(i)<span class="operator">.</span>toString();
             <span class="keyword">break</span>;
         }
     }
     <span class="comment">// if we did not find one, use IPv4 localhost</span>
     <span class="keyword">if</span> (ipAddress<span class="operator">.</span>isEmpty())
         ipAddress <span class="operator">=</span> <span class="type"><a href="qhostaddress.html">QHostAddress</a></span>(<span class="type"><a href="qhostaddress.html">QHostAddress</a></span><span class="operator">::</span>LocalHost)<span class="operator">.</span>toString();
     statusLabel<span class="operator">-</span><span class="operator">&gt;</span>setText(tr(<span class="string">&quot;The server is running on\n\nIP: %1\nport: %2\n\n&quot;</span>
                             <span class="string">&quot;Run the Fortune Client example now.&quot;</span>)
                          <span class="operator">.</span>arg(ipAddress)<span class="operator">.</span>arg(tcpServer<span class="operator">-</span><span class="operator">&gt;</span>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 class="cpp">     fortunes <span class="operator">&lt;</span><span class="operator">&lt;</span> tr(<span class="string">&quot;You've been leading a dog's life. Stay off the furniture.&quot;</span>)
              <span class="operator">&lt;</span><span class="operator">&lt;</span> tr(<span class="string">&quot;You've got to think about tomorrow.&quot;</span>)
              <span class="operator">&lt;</span><span class="operator">&lt;</span> tr(<span class="string">&quot;You will be surprised by a loud noise.&quot;</span>)
              <span class="operator">&lt;</span><span class="operator">&lt;</span> tr(<span class="string">&quot;You will feel hungry again in another hour.&quot;</span>)
              <span class="operator">&lt;</span><span class="operator">&lt;</span> tr(<span class="string">&quot;You might have mail.&quot;</span>)
              <span class="operator">&lt;</span><span class="operator">&lt;</span> tr(<span class="string">&quot;You cannot kill time without injuring eternity.&quot;</span>)
              <span class="operator">&lt;</span><span class="operator">&lt;</span> tr(<span class="string">&quot;Computers are not intelligent. They only think they are.&quot;</span>);</pre>
<p>Our server generates a list of random fortunes that is can send to connecting clients.</p>
<pre class="cpp">     connect(tcpServer<span class="operator">,</span> SIGNAL(newConnection())<span class="operator">,</span> <span class="keyword">this</span><span class="operator">,</span> 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 class="cpp"> <span class="type">void</span> Server<span class="operator">::</span>sendFortune()
 {
     <span class="type"><a href="qbytearray.html">QByteArray</a></span> block;
     <span class="type"><a href="qdatastream.html">QDataStream</a></span> out(<span class="operator">&amp;</span>block<span class="operator">,</span> <span class="type"><a href="qiodevice.html">QIODevice</a></span><span class="operator">::</span>WriteOnly);
     out<span class="operator">.</span>setVersion(<span class="type"><a href="qdatastream.html">QDataStream</a></span><span class="operator">::</span>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 class="cpp">     out <span class="operator">&lt;</span><span class="operator">&lt;</span> (<span class="type"><a href="qtglobal.html#quint16-typedef">quint16</a></span>)<span class="number">0</span>;
     out <span class="operator">&lt;</span><span class="operator">&lt;</span> fortunes<span class="operator">.</span>at(qrand() <span class="operator">%</span> fortunes<span class="operator">.</span>size());
     out<span class="operator">.</span>device()<span class="operator">-</span><span class="operator">&gt;</span>seek(<span class="number">0</span>);
     out <span class="operator">&lt;</span><span class="operator">&lt;</span> (<span class="type"><a href="qtglobal.html#quint16-typedef">quint16</a></span>)(block<span class="operator">.</span>size() <span class="operator">-</span> <span class="keyword">sizeof</span>(<span class="type"><a href="qtglobal.html#quint16-typedef">quint16</a></span>));</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 class="cpp">     <span class="type"><a href="qtcpsocket.html">QTcpSocket</a></span> <span class="operator">*</span>clientConnection <span class="operator">=</span> tcpServer<span class="operator">-</span><span class="operator">&gt;</span>nextPendingConnection();
     connect(clientConnection<span class="operator">,</span> SIGNAL(disconnected())<span class="operator">,</span>
             clientConnection<span class="operator">,</span> 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 class="cpp">     clientConnection<span class="operator">-</span><span class="operator">&gt;</span>write(block);
     clientConnection<span class="operator">-</span><span class="operator">&gt;</span>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>
</div>
<p><b>See also </b><a href="network-fortuneclient.html">Fortune Client Example</a> and <a href="network-threadedfortuneserver.html">Threaded Fortune Server Example</a>.</p>
<!-- @@@network/fortuneserver -->
  <div class="ft">
    <span></span>
  </div>
</div> 
<div class="footer">
    <p>
      <acronym title="Copyright">&copy;</acronym> 2012 Nokia Corporation and/or its
      subsidiaries. Documentation contributions included herein are the copyrights of
      their respective owners.</p>
    <br />
    <p>
      The documentation provided herein is licensed under the terms of the
      <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation
      License version 1.3</a> as published by the Free Software Foundation.</p>
    <p>
      Documentation sources may be obtained from <a href="http://www.qt-project.org">
      www.qt-project.org</a>.</p>
    <br />
    <p>
      Nokia, Qt and their respective logos are trademarks of Nokia Corporation 
      in Finland and/or other countries worldwide. All other trademarks are property
      of their respective owners. <a title="Privacy Policy"
      href="http://en.gitorious.org/privacy_policy/">Privacy Policy</a></p>
</div>
</body>
</html>