<?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"> <!-- /home/gvatteka/dev/qt-4.3/doc/src/qt4-network.qdoc --> <head> <title>The Network Module in Qt 4</title> <link href="classic.css" rel="stylesheet" type="text/css" /> </head> <body> <h1 align="center">The Network Module in Qt 4<br /><small></small></h1> <p>The network module in Qt 4 provides some new features, such as support for internationalized domain names, better IPv6 support, and better performance. And since Qt 4 allows us to break binary compatibility with previous releases, we took this opportunity to improve the class names and API to make them more intuitive to use.</p> <ul><li><a href="#general-overview">General Overview</a></li> <li><a href="#example-code">Example Code</a></li> <ul><li><a href="#tcp-client">TCP Client</a></li> <li><a href="#tcp-server">TCP Server</a></li> <li><a href="#udp-senders-and-receivers">UDP Senders and Receivers</a></li> </ul> <li><a href="#comparison-with-qt-3">Comparison with Qt 3</a></li> </ul> <a name="general-overview"></a> <h2>General Overview</h2> <p>Compared to Qt 3, the network module in Qt 4 brings the following benefits:</p> <ul> <li>The Qt 4 network classes have more intuitive names and APIs. For example, <a href="porting4.html#qserversocket"><tt>QServerSocket</tt></a> has been renamed <a href="network/QTcpServer.html"><tt>QTcpServer</tt></a>.</li> <li>The entire network module is <a href="threads.html#reentrant">reentrant</tt></a>, making it possible to use them simultaneously from multiple threads.</li> <li>It is now possible to send and receive UDP datagrams and to use synchronous (i.e., blocking) sockets without having to use a low-level API (<a href="porting4.html#qsocketdevice"><tt>QSocketDevice</tt></a> in Qt 3).</li> <li><a href="network/QHostAddress.html"><tt>QHostAddress</tt></a> and <a href="network/QHostInfo.html"><tt>QHostInfo</tt></a> support internationalized domain names (RFC 3492).</li> <li><a href="core/QUrl.html"><tt>QUrl</tt></a> is more lightweight and fully supports the latest URI specification draft.</li> <li>UDP broadcasting is now supported.</li> </ul> <p>The Qt 4 network module provides fundamental classes for writing TCP and UDP applications, as well as higher-level classes that implement the client side of the HTTP and FTP protocols.</p> <p>Here's an overview of the TCP and UDP classes:</p> <ul> <li><a href="network/QTcpSocket.html"><tt>QTcpSocket</tt></a> encapsulates a TCP socket. It inherits from <a href="core/QIODevice.html"><tt>QIODevice</tt></a>, so you can use <a href="core/QTextStream.html"><tt>QTextStream</tt></a> and <a href="core/QDataStream.html"><tt>QDataStream</tt></a> to read or write data. It is useful for writing both clients and servers.</li> <li><a href="network/QTcpServer.html"><tt>QTcpServer</tt></a> allows you to listen on a certain port on a server. It emits a newConnection() signal every time a client tries to connect to the server. Once the connection is established, you can talk to the client using <a href="network/QTcpSocket.html"><tt>QTcpSocket</tt></a>.</li> <li><a href="network/QUdpSocket.html"><tt>QUdpSocket</tt></a> is an API for sending and receiving UDP datagrams.</li> </ul> <p><a href="network/QTcpSocket.html"><tt>QTcpSocket</tt></a> and <a href="network/QUdpSocket.html"><tt>QUdpSocket</tt></a> inherit most of their functionality from <a href="network/QAbstractSocket.html"><tt>QAbstractSocket</tt></a>. You can also use <a href="network/QAbstractSocket.html"><tt>QAbstractSocket</tt></a> directly as a wrapper around a native socket descriptor.</p> <p>By default, the socket classes work asynchronously (i.e., they are non-blocking), emitting signals to notify when data has arrived or when the peer has closed the connection. In multithreaded applications and in non-GUI applications, you also have the opportunity of using blocking (synchronous) functions on the socket, which often results in a more straightforward style of programming, with the networking logic concentrated in one or two functions instead of spread across multiple slots.</p> <p><a href="network/QFtp.html"><tt>QFtp</tt></a> and <a href="network/QHttp.html"><tt>QHttp</tt></a> use <a href="network/QTcpSocket.html"><tt>QTcpSocket</tt></a> internally to implement the FTP and HTTP protocols. Both classes work asynchronously and can schedule (i.e., queue) requests.</p> <p>The network module contains four helper classes: <a href="network/QHostAddress.html"><tt>QHostAddress</tt></a>, <a href="network/QHostInfo.html"><tt>QHostInfo</tt></a>, <a href="core/QUrl.html"><tt>QUrl</tt></a>, and <a href="network/QUrlInfo.html"><tt>QUrlInfo</tt></a>. <a href="network/QHostAddress.html"><tt>QHostAddress</tt></a> stores an IPv4 or IPv6 address, <a href="network/QHostInfo.html"><tt>QHostInfo</tt></a> resolves host names into addresses, <a href="core/QUrl.html"><tt>QUrl</tt></a> stores a URL, and <a href="network/QUrlInfo.html"><tt>QUrlInfo</tt></a> stores information about a resource pointed to by a URL, such as the file size and modification date. (Because <a href="core/QUrl.html"><tt>QUrl</tt></a> is used by <a href="gui/QTextBrowser.html"><tt>QTextBrowser</tt></a>, it is part of the QtCore library and not of QtNetwork.)</p> <p>See the <tt>QtNetwork</tt> module overview for more information.</p> <a name="example-code"></a> <h2>Example Code</h2> <p>All the code snippets presented here are quoted from self-contained, compilable examples located in Qt's <tt>examples/network</tt> directory.</p> <a name="tcp-client"></a> <h3>TCP Client</h3> <p>The first example illustrates how to write a TCP client using <a href="network/QTcpSocket.html"><tt>QTcpSocket</tt></a>. The client talks to a fortune server that provides fortune to the user. Here's how to set up the socket:</p> <pre> tcpSocket = new QTcpSocket(this); connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readFortune())); connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));</pre> <p>When the user requests a new fortune, the client establishes a connection to the server:</p> <pre> tcpSocket->connectToHost(hostLineEdit->text(), portLineEdit->text().toInt());</pre> <p>When the server answers, the following code is executed to read the data from the socket:</p> <pre> QDataStream in(tcpSocket); in.setVersion(QDataStream::Qt_4_0); if (blockSize == 0) { if (tcpSocket->bytesAvailable() < (int)sizeof(quint16)) return; in >> blockSize; } if (tcpSocket->bytesAvailable() < blockSize) return; QString nextFortune; in >> nextFortune; if (nextFortune == currentFortune) { QTimer::singleShot(0, this, SLOT(requestNewFortune())); return; } currentFortune = nextFortune;</pre> <p>The server's answer starts with a <i>size</i> field (which we store in <tt>blockSize</tt>), followed by <i>size</i> bytes of data. If the client hasn't received all the data yet, it waits for the server to send more.</p> <p>An alternative approach is to use a blocking socket. The code can then be concentrated in one function:</p> <pre> const int Timeout = 5 * 1000; QTcpSocket socket; socket.connectToHost(serverName, serverPort); if (!socket.waitForConnected(Timeout)) { emit error(socket.error(), socket.errorString()); return; } while (socket.bytesAvailable() < (int)sizeof(quint16)) { if (!socket.waitForReadyRead(Timeout)) { emit error(socket.error(), socket.errorString()); return; } } quint16 blockSize; QDataStream in(&socket); in.setVersion(QDataStream::Qt_4_0); in >> blockSize; while (socket.bytesAvailable() < blockSize) { if (!socket.waitForReadyRead(Timeout)) { emit error(socket.error(), socket.errorString()); return; } } QMutexLocker locker(&mutex); QString fortune; in >> fortune; emit newFortune(fortune);</pre> <a name="tcp-server"></a> <h3>TCP Server</h3> <p>The following code snippets illustrate how to write a TCP server using <a href="network/QTcpServer.html"><tt>QTcpServer</tt></a> and <a href="network/QTcpSocket.html"><tt>QTcpSocket</tt></a>. Here's how to set up a TCP server:</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; } connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendFortune()));</pre> <p>When a client tries to connect to the server, the following code in the sendFortune() slot is executed:</p> <pre> QByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_4_0); out << (quint16)0; out << fortunes.at(qrand() % fortunes.size()); out.device()->seek(0); out << (quint16)(block.size() - sizeof(quint16)); QTcpSocket *clientConnection = tcpServer->nextPendingConnection(); connect(clientConnection, SIGNAL(disconnected()), clientConnection, SLOT(deleteLater())); clientConnection->write(block); clientConnection->disconnectFromHost();</pre> <a name="udp-senders-and-receivers"></a> <h3>UDP Senders and Receivers</h3> <p>Here's how to broadcast a UDP datagram:</p> <pre> udpSocket = new QUdpSocket(this); QByteArray datagram = "Broadcast message " + QByteArray::number(messageNo); udpSocket->writeDatagram(datagram.data(), datagram.size(), QHostAddress::Broadcast, 45454);</pre> <p>Here's how to receive a UDP datagram:</p> <pre> udpSocket = new QUdpSocket(this); udpSocket->bind(45454); connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));</pre> <p>Then in the processPendingDatagrams() slot:</p> <pre> while (udpSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(datagram.data(), datagram.size()); statusLabel->setText(tr("Received datagram: \"%1\"") .arg(datagram.data())); }</pre> <a name="comparison-with-qt-3"></a> <h2>Comparison with Qt 3</h2> <p>The main difference between Qt 3 and Qt 4 is that the very high level <a href="porting4.html#qnetworkprotocol"><tt>QNetworkProtocol</tt></a> and <a href="porting4.html#qurloperator"><tt>QUrlOperator</tt></a> abstraction has been eliminated. These classes attempted the impossible (unify FTP and HTTP under one roof), and unsurprisingly failed at that. Qt 4 still provides <a href="network/QFtp.html"><tt>QFtp</tt></a> and <a href="network/QHttp.html"><tt>QHttp</tt></a> classes, but only with the more mature API that appeared in Qt 3.1.</p> <p>The <a href="porting4.html#qsocket"><tt>QSocket</tt></a> class in Qt 3 has been renamed <a href="network/QTcpSocket.html"><tt>QTcpSocket</tt></a>. The new class is reentrant and supports blocking. It's also easier to handle closing than with Qt 3, where you had to connect to both the QSocket::connectionClosed() and the QSocket::delayedCloseFinished() signals.</p> <p>The <a href="porting4.html#qserversocket"><tt>QServerSocket</tt></a> class in Qt 3 has been renamed <a href="network/QTcpServer.html"><tt>QTcpServer</tt></a>. The API has changed quite a bit. While in Qt 3 it was necessary to subclass <a href="porting4.html#qserversocket"><tt>QServerSocket</tt></a> and reimplement the newConnection() pure virtual function, <a href="network/QTcpServer.html"><tt>QTcpServer</tt></a> now emits a newConnection() signal that you can connect to a slot.</p> <p>The <a href="network/QHostInfo.html"><tt>QHostInfo</tt></a> class has been redesigned to use the operating system's getaddrinfo() function instead of implementing the DNS protocol. Internally, <a href="network/QHostInfo.html"><tt>QHostInfo</tt></a> simply starts a thread and calls getaddrinfo() in that thread. This wasn't possible in Qt 3 because getaddrinfo() is a blocking call and Qt 3 could be configured without multithreading support.</p> <p>The <a href="porting4.html#qsocketdevice"><tt>QSocketDevice</tt></a> class in Qt 3 is no longer part of the public Qt API. If you used <a href="porting4.html#qsocketdevice"><tt>QSocketDevice</tt></a> to send or receive UDP datagrams, use <a href="network/QUdpSocket.html"><tt>QUdpSocket</tt></a> instead. If you used <a href="porting4.html#qsocketdevice"><tt>QSocketDevice</tt></a> because it supported blocking sockets, use <a href="network/QTcpSocket.html"><tt>QTcpSocket</tt></a> or <a href="network/QUdpSocket.html"><tt>QUdpSocket</tt></a> instead and use the blocking functions (waitForConnected(), waitForReadyRead(), etc.). If you used <a href="porting4.html#qsocketdevice"><tt>QSocketDevice</tt></a> from a non-GUI thread because it was the only reentrant networking class in Qt 3, use <a href="network/QTcpSocket.html"><tt>QTcpSocket</tt></a>, <a href="network/QTcpServer.html"><tt>QTcpServer</tt></a>, or <a href="network/QUdpSocket.html"><tt>QUdpSocket</tt></a> instead.</p> <p>Internally, Qt 4 has a class called QSocketLayer that provides a cross-platform low-level socket API. It resembles the old <a href="porting4.html#qsocketdevice"><tt>QSocketDevice</tt></a> class. We might make it public in a later release if users ask for it.</p> <p>As an aid to porting to Qt 4, the <tt>Qt3Support</tt> library includes Q3Dns, Q3ServerSocket, Q3Socket, and Q3SocketDevice classes.</p> <p /><address><hr /><div align="center"> <table width="100%" cellspacing="0" border="0"><tr class="address"> <td width="30%">Copyright © 2007 <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 Jambi </div></td> </tr></table></div></address></body> </html>