C++/Qt/QTcpServer

Материал из C\C++ эксперт
Перейти к: навигация, поиск

Loopback QTcpServer and QTcpSocket

<source lang="cpp"> /****************************************************************************

    • Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    • All rights reserved.
    • Contact: Nokia Corporation (qt-info@nokia.com)
    • This file is part of the examples of the Qt Toolkit.
    • $QT_BEGIN_LICENSE:LGPL$
    • Commercial Usage
    • Licensees holding valid Qt Commercial licenses may use this file in
    • accordance with the Qt Commercial License Agreement provided with the
    • Software or, alternatively, in accordance with the terms contained in
    • a written agreement between you and Nokia.
    • GNU Lesser General Public License Usage
    • Alternatively, this file may be used under the terms of the GNU Lesser
    • General Public License version 2.1 as published by the Free Software
    • Foundation and appearing in the file LICENSE.LGPL included in the
    • packaging of this file. Please review the following information to
    • ensure the GNU Lesser General Public License version 2.1 requirements
    • will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    • In addition, as a special exception, Nokia gives you certain additional
    • rights. These rights are described in the Nokia Qt LGPL Exception
    • version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    • GNU General Public License Usage
    • Alternatively, this file may be used under the terms of the GNU
    • General Public License version 3.0 as published by the Free Software
    • Foundation and appearing in the file LICENSE.GPL included in the
    • packaging of this file. Please review the following information to
    • ensure the GNU General Public License version 3.0 requirements will be
    • met: http://www.gnu.org/copyleft/gpl.html.
    • If you have questions regarding the use of this file, please contact
    • Nokia at qt-info@nokia.com.
    • $QT_END_LICENSE$
                                                                                                                                                        • /
  1. ifndef DIALOG_H
  2. define DIALOG_H
  3. include <QDialog>
  4. include <QTcpServer>
  5. include <QTcpSocket>

QT_BEGIN_NAMESPACE class QDialogButtonBox; class QLabel; class QProgressBar; class QPushButton; class QTcpServer; class QTcpSocket; QT_END_NAMESPACE class Dialog : public QDialog {

   Q_OBJECT

public:

   Dialog(QWidget *parent = 0);

public slots:

   void start();
   void acceptConnection();
   void startTransfer();
   void updateServerProgress();
   void updateClientProgress(qint64 numBytes);
   void displayError(QAbstractSocket::SocketError socketError);

private:

   QProgressBar *clientProgressBar;
   QProgressBar *serverProgressBar;
   QLabel *clientStatusLabel;
   QLabel *serverStatusLabel;
   QPushButton *startButton;
   QPushButton *quitButton;
   QDialogButtonBox *buttonBox;
   QTcpServer tcpServer;
   QTcpSocket tcpClient;
   QTcpSocket *tcpServerConnection;
   int bytesToWrite;
   int bytesWritten;
   int bytesReceived;

};

  1. endif


  1. include <QtGui>
  2. include <QtNetwork>
  3. include "dialog.h"
  4. if !defined(Q_OS_WINCE)

static const int TotalBytes = 50 * 1024 * 1024;

  1. else

static const int TotalBytes = 5 * 1024 * 1024;

  1. endif

static const int PayloadSize = 65536; Dialog::Dialog(QWidget *parent)

   : QDialog(parent)

{

   clientProgressBar = new QProgressBar;
   clientStatusLabel = new QLabel(tr("Client ready"));
   serverProgressBar = new QProgressBar;
   serverStatusLabel = new QLabel(tr("Server ready"));
   startButton = new QPushButton(tr("&Start"));
   quitButton = new QPushButton(tr("&Quit"));
   buttonBox = new QDialogButtonBox;
   buttonBox->addButton(startButton, QDialogButtonBox::ActionRole);
   buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
   connect(startButton, SIGNAL(clicked()), this, SLOT(start()));
   connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
   connect(&tcpServer, SIGNAL(newConnection()),
           this, SLOT(acceptConnection()));
   connect(&tcpClient, SIGNAL(connected()), this, SLOT(startTransfer()));
   connect(&tcpClient, SIGNAL(bytesWritten(qint64)),
           this, SLOT(updateClientProgress(qint64)));
   connect(&tcpClient, SIGNAL(error(QAbstractSocket::SocketError)),
           this, SLOT(displayError(QAbstractSocket::SocketError)));
   QVBoxLayout *mainLayout = new QVBoxLayout;
   mainLayout->addWidget(clientProgressBar);
   mainLayout->addWidget(clientStatusLabel);
   mainLayout->addWidget(serverProgressBar);
   mainLayout->addWidget(serverStatusLabel);
   mainLayout->addStretch(1);
   mainLayout->addSpacing(10);
   mainLayout->addWidget(buttonBox);
   setLayout(mainLayout);
   setWindowTitle(tr("Loopback"));

} void Dialog::start() {

   startButton->setEnabled(false);
  1. ifndef QT_NO_CURSOR
   QApplication::setOverrideCursor(Qt::WaitCursor);
  1. endif
   bytesWritten = 0;
   bytesReceived = 0;
   while (!tcpServer.isListening() && !tcpServer.listen()) {
       QMessageBox::StandardButton ret = QMessageBox::critical(this,
                                       tr("Loopback"),
                                       tr("Unable to start the test: %1.")
         .arg(tcpServer.errorString()),
                                       QMessageBox::Retry
         | QMessageBox::Cancel);
       if (ret == QMessageBox::Cancel)
           return;
   }
   serverStatusLabel->setText(tr("Listening"));
   clientStatusLabel->setText(tr("Connecting"));
   tcpClient.connectToHost(QHostAddress::LocalHost, tcpServer.serverPort());

} void Dialog::acceptConnection() {

   tcpServerConnection = tcpServer.nextPendingConnection();
   connect(tcpServerConnection, SIGNAL(readyRead()),
           this, SLOT(updateServerProgress()));
   connect(tcpServerConnection, SIGNAL(error(QAbstractSocket::SocketError)),
           this, SLOT(displayError(QAbstractSocket::SocketError)));
   serverStatusLabel->setText(tr("Accepted connection"));
   tcpServer.close();

} void Dialog::startTransfer() {

   bytesToWrite = TotalBytes - (int)tcpClient.write(QByteArray(PayloadSize, "@"));
   clientStatusLabel->setText(tr("Connected"));

} void Dialog::updateServerProgress() {

   bytesReceived += (int)tcpServerConnection->bytesAvailable();
   tcpServerConnection->readAll();
   serverProgressBar->setMaximum(TotalBytes);
   serverProgressBar->setValue(bytesReceived);
   serverStatusLabel->setText(tr("Received %1MB")
                              .arg(bytesReceived / (1024 * 1024)));
   if (bytesReceived == TotalBytes) {
       tcpServerConnection->close();
       startButton->setEnabled(true);
  1. ifndef QT_NO_CURSOR
       QApplication::restoreOverrideCursor();
  1. endif
   }

} void Dialog::updateClientProgress(qint64 numBytes) {

   bytesWritten += (int)numBytes;
   if (bytesToWrite > 0)
       bytesToWrite -= (int)tcpClient.write(QByteArray(qMin(bytesToWrite, PayloadSize), "@"));
   clientProgressBar->setMaximum(TotalBytes);
   clientProgressBar->setValue(bytesWritten);
   clientStatusLabel->setText(tr("Sent %1MB")
                              .arg(bytesWritten / (1024 * 1024)));

} void Dialog::displayError(QAbstractSocket::SocketError socketError) {

   if (socketError == QTcpSocket::RemoteHostClosedError)
       return;
   QMessageBox::information(this, tr("Network error"),
                            tr("The following error occurred: %1.")
                            .arg(tcpClient.errorString()));
   tcpClient.close();
   tcpServer.close();
   clientProgressBar->reset();
   serverProgressBar->reset();
   clientStatusLabel->setText(tr("Client ready"));
   serverStatusLabel->setText(tr("Server ready"));
   startButton->setEnabled(true);
  1. ifndef QT_NO_CURSOR
   QApplication::restoreOverrideCursor();
  1. endif

}


  1. include <QApplication>
  2. include "dialog.h"

int main(int argc, char *argv[]) {

   QApplication app(argc, argv);
   Dialog dialog;
   dialog.show();
   return dialog.exec();

}


 </source>


QTcpServer based server

<source lang="cpp">

Foundations of Qt Development\Chapter14\tcpserver\main.cpp /*

* Copyright (c) 2006-2007, Johan Thelin
* 
* All rights reserved.
* 
* Redistribution and use in source and binary forms, with or without modification, 
* are permitted provided that the following conditions are met:
* 
*     * Redistributions of source code must retain the above copyright notice, 
*       this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice,  
*       this list of conditions and the following disclaimer in the documentation 
*       and/or other materials provided with the distribution.
*     * Neither the name of APress nor the names of its contributors 
*       may be used to endorse or promote products derived from this software 
*       without specific prior written permission.
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
  1. include <QCoreApplication>
  2. include "server.h"

int main( int argc, char **argv ) {

 QCoreApplication app( argc, argv );
 
 Server server;
 if( !server.listen( QHostAddress::Any, 9876 ) )
 {
   qCritical( "Cannot listen to port 9876." );
   return 1;
 }
 
 return app.exec();

}

Foundations of Qt Development\Chapter14\tcpserver\server.cpp /*

* Copyright (c) 2006-2007, Johan Thelin
* 
* All rights reserved.
* 
* Redistribution and use in source and binary forms, with or without modification, 
* are permitted provided that the following conditions are met:
* 
*     * Redistributions of source code must retain the above copyright notice, 
*       this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice,  
*       this list of conditions and the following disclaimer in the documentation 
*       and/or other materials provided with the distribution.
*     * Neither the name of APress nor the names of its contributors 
*       may be used to endorse or promote products derived from this software 
*       without specific prior written permission.
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
  1. include <QTcpServer>
  2. include <QTcpSocket>
  3. include "server.h"
  4. include "serverthread.h"

Server::Server() : QTcpServer() { } void Server::incomingConnection( int descriptor ) {

 ServerThread *thread = new ServerThread( descriptor, this );
 
 connect( thread, SIGNAL(finished()), thread, SLOT(deleteLater()) );
 thread->start();

}

Foundations of Qt Development\Chapter14\tcpserver\server.h /*

* Copyright (c) 2006-2007, Johan Thelin
* 
* All rights reserved.
* 
* Redistribution and use in source and binary forms, with or without modification, 
* are permitted provided that the following conditions are met:
* 
*     * Redistributions of source code must retain the above copyright notice, 
*       this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice,  
*       this list of conditions and the following disclaimer in the documentation 
*       and/or other materials provided with the distribution.
*     * Neither the name of APress nor the names of its contributors 
*       may be used to endorse or promote products derived from this software 
*       without specific prior written permission.
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
  1. ifndef SERVER_H
  2. define SERVER_H
  3. include <QTcpServer>

class Server : public QTcpServer { public:

 Server();
 

protected:

 void incomingConnection( int descriptor );

};

  1. endif // SERVER_H

Foundations of Qt Development\Chapter14\tcpserver\serverthread.cpp /*

* Copyright (c) 2006-2007, Johan Thelin
* 
* All rights reserved.
* 
* Redistribution and use in source and binary forms, with or without modification, 
* are permitted provided that the following conditions are met:
* 
*     * Redistributions of source code must retain the above copyright notice, 
*       this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice,  
*       this list of conditions and the following disclaimer in the documentation 
*       and/or other materials provided with the distribution.
*     * Neither the name of APress nor the names of its contributors 
*       may be used to endorse or promote products derived from this software 
*       without specific prior written permission.
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
  1. include <QBuffer>
  2. include <QImage>
  3. include <QImageWriter>
  4. include <QTcpSocket>
  5. include <QDir>
  6. include <QTime>
  7. include "serverthread.h"

ServerThread::ServerThread( int descriptor, QObject *parent ) : QThread( parent ) {

 m_descriptor = descriptor;

} void ServerThread::run() {

 QTcpSocket socket;
 
 if( !socket.setSocketDescriptor( m_descriptor ) )
 {
   qDebug( "Socket error!" );
   return;
 }
 
 QBuffer buffer;
 QImageWriter writer(&buffer, "PNG");
 writer.write( randomImage() );
 
 QByteArray data;
 QDataStream stream( &data, QIODevice::WriteOnly );
 stream.setVersion( QDataStream::Qt_4_0 );
 stream << (quint32)buffer.data().size();
 data.append( buffer.data() );
 
 socket.write( data );
 
 socket.disconnectFromHost();
 socket.waitForDisconnected();

} QImage ServerThread::randomImage() {

 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
 
 QDir dir("./images");
 dir.setFilter( QDir::Files );
 QFileInfoList entries = dir.entryInfoList();
 
 if( entries.size() == 0 )
 {
   qDebug( "No images to show!" );
   return QImage();
 }
 
 return QImage( entries.at( qrand() % entries.size() ).absoluteFilePath() );

}

Foundations of Qt Development\Chapter14\tcpserver\serverthread.h /*

* Copyright (c) 2006-2007, Johan Thelin
* 
* All rights reserved.
* 
* Redistribution and use in source and binary forms, with or without modification, 
* are permitted provided that the following conditions are met:
* 
*     * Redistributions of source code must retain the above copyright notice, 
*       this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice,  
*       this list of conditions and the following disclaimer in the documentation 
*       and/or other materials provided with the distribution.
*     * Neither the name of APress nor the names of its contributors 
*       may be used to endorse or promote products derived from this software 
*       without specific prior written permission.
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
  1. ifndef SERVERTHREAD_H
  2. define SERVERTHREAD_H
  3. include <QThread>
  4. include <QImage>

class ServerThread : public QThread { public:

 ServerThread( int descriptor, QObject *parent );
 
 void run();

private:

 QImage randomImage();
 
 int m_descriptor;

};

  1. endif // SERVERTHREAD_H


 </source>


QTcpServer based server 2

<source lang="cpp">

/****************************************************************************

    • Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    • All rights reserved.
    • Contact: Nokia Corporation (qt-info@nokia.com)
    • This file is part of the examples of the Qt Toolkit.
    • $QT_BEGIN_LICENSE:LGPL$
    • Commercial Usage
    • Licensees holding valid Qt Commercial licenses may use this file in
    • accordance with the Qt Commercial License Agreement provided with the
    • Software or, alternatively, in accordance with the terms contained in
    • a written agreement between you and Nokia.
    • GNU Lesser General Public License Usage
    • Alternatively, this file may be used under the terms of the GNU Lesser
    • General Public License version 2.1 as published by the Free Software
    • Foundation and appearing in the file LICENSE.LGPL included in the
    • packaging of this file. Please review the following information to
    • ensure the GNU Lesser General Public License version 2.1 requirements
    • will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    • In addition, as a special exception, Nokia gives you certain additional
    • rights. These rights are described in the Nokia Qt LGPL Exception
    • version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    • GNU General Public License Usage
    • Alternatively, this file may be used under the terms of the GNU
    • General Public License version 3.0 as published by the Free Software
    • Foundation and appearing in the file LICENSE.GPL included in the
    • packaging of this file. Please review the following information to
    • ensure the GNU General Public License version 3.0 requirements will be
    • met: http://www.gnu.org/copyleft/gpl.html.
    • If you have questions regarding the use of this file, please contact
    • Nokia at qt-info@nokia.com.
    • $QT_END_LICENSE$
                                                                                                                                                        • /
  1. ifndef SERVER_H
  2. define SERVER_H
  3. include <QDialog>

QT_BEGIN_NAMESPACE class QLabel; class QPushButton; class QTcpServer; QT_END_NAMESPACE

class Server : public QDialog {

   Q_OBJECT

public:

   Server(QWidget *parent = 0);

private slots:

   void sendFortune();

private:

   QLabel *statusLabel;
   QPushButton *quitButton;
   QTcpServer *tcpServer;
   QStringList fortunes;

};

  1. endif


  1. include <QtGui>
  2. include <QtNetwork>
  3. include <stdlib.h>
  4. include "server.h"

Server::Server(QWidget *parent)

   : QDialog(parent)

{

   statusLabel = new QLabel;
   quitButton = new QPushButton(tr("Quit"));
   quitButton->setAutoDefault(false);

   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()));
   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.");
   connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
   connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendFortune()));
   QHBoxLayout *buttonLayout = new QHBoxLayout;
   buttonLayout->addStretch(1);
   buttonLayout->addWidget(quitButton);
   buttonLayout->addStretch(1);
   QVBoxLayout *mainLayout = new QVBoxLayout;
   mainLayout->addWidget(statusLabel);
   mainLayout->addLayout(buttonLayout);
   setLayout(mainLayout);
   setWindowTitle(tr("Fortune Server"));

}

void Server::sendFortune() {

   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();

}


  1. include <QApplication>
  2. include <QtCore>
  3. include <stdlib.h>
  4. include "server.h"

int main(int argc, char *argv[]) {

   QApplication app(argc, argv);
   Server server;
   server.show();
   qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
   return server.exec();

}


 </source>


Thread based server

<source lang="cpp"> /****************************************************************************

    • Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    • All rights reserved.
    • Contact: Nokia Corporation (qt-info@nokia.com)
    • This file is part of the examples of the Qt Toolkit.
    • $QT_BEGIN_LICENSE:LGPL$
    • Commercial Usage
    • Licensees holding valid Qt Commercial licenses may use this file in
    • accordance with the Qt Commercial License Agreement provided with the
    • Software or, alternatively, in accordance with the terms contained in
    • a written agreement between you and Nokia.
    • GNU Lesser General Public License Usage
    • Alternatively, this file may be used under the terms of the GNU Lesser
    • General Public License version 2.1 as published by the Free Software
    • Foundation and appearing in the file LICENSE.LGPL included in the
    • packaging of this file. Please review the following information to
    • ensure the GNU Lesser General Public License version 2.1 requirements
    • will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    • In addition, as a special exception, Nokia gives you certain additional
    • rights. These rights are described in the Nokia Qt LGPL Exception
    • version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    • GNU General Public License Usage
    • Alternatively, this file may be used under the terms of the GNU
    • General Public License version 3.0 as published by the Free Software
    • Foundation and appearing in the file LICENSE.GPL included in the
    • packaging of this file. Please review the following information to
    • ensure the GNU General Public License version 3.0 requirements will be
    • met: http://www.gnu.org/copyleft/gpl.html.
    • If you have questions regarding the use of this file, please contact
    • Nokia at qt-info@nokia.com.
    • $QT_END_LICENSE$
                                                                                                                                                        • /
  1. ifndef FORTUNESERVER_H
  2. define FORTUNESERVER_H
  3. include <QStringList>
  4. include <QTcpServer>

class FortuneServer : public QTcpServer {

   Q_OBJECT

public:

   FortuneServer(QObject *parent = 0);

protected:

   void incomingConnection(int socketDescriptor);

private:

   QStringList fortunes;

};

  1. endif



  1. include "fortuneserver.h"
  2. include "fortunethread.h"
  3. include <stdlib.h>

FortuneServer::FortuneServer(QObject *parent)

   : QTcpServer(parent)

{

   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.");

}

void FortuneServer::incomingConnection(int socketDescriptor) {

   QString fortune = fortunes.at(qrand() % fortunes.size());
   FortuneThread *thread = new FortuneThread(socketDescriptor, fortune, this);
   connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
   thread->start();

}


  1. ifndef DIALOG_H
  2. define DIALOG_H
  3. include <QDialog>
  4. include "fortuneserver.h"

QT_BEGIN_NAMESPACE class QLabel; class QPushButton; QT_END_NAMESPACE class Dialog : public QDialog {

   Q_OBJECT

public:

   Dialog(QWidget *parent = 0);

private:

   QLabel *statusLabel;
   QPushButton *quitButton;
   FortuneServer server;

};

  1. endif


  1. include <QtGui>
  2. include <QtNetwork>
  3. include <stdlib.h>
  4. include "dialog.h"
  5. include "fortuneserver.h"

Dialog::Dialog(QWidget *parent)

   : QDialog(parent)

{

   statusLabel = new QLabel;
   quitButton = new QPushButton(tr("Quit"));
   quitButton->setAutoDefault(false);
   if (!server.listen()) {
       QMessageBox::critical(this, tr("Threaded Fortune Server"),
                             tr("Unable to start the server: %1.")
                             .arg(server.errorString()));
       close();
       return;
   }
   statusLabel->setText(tr("The server is running on port %1.\n"
                           "Run the Fortune Client example now.")
                        .arg(server.serverPort()));
   connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
   QHBoxLayout *buttonLayout = new QHBoxLayout;
   buttonLayout->addStretch(1);
   buttonLayout->addWidget(quitButton);
   buttonLayout->addStretch(1);
   QVBoxLayout *mainLayout = new QVBoxLayout;
   mainLayout->addWidget(statusLabel);
   mainLayout->addLayout(buttonLayout);
   setLayout(mainLayout);
   setWindowTitle(tr("Threaded Fortune Server"));

}


  1. ifndef FORTUNETHREAD_H
  2. define FORTUNETHREAD_H
  3. include <QThread>
  4. include <QTcpSocket>

class FortuneThread : public QThread {

   Q_OBJECT

public:

   FortuneThread(int socketDescriptor, const QString &fortune, QObject *parent);
   void run();

signals:

   void error(QTcpSocket::SocketError socketError);

private:

   int socketDescriptor;
   QString text;

};

  1. endif


  1. include "fortunethread.h"
  2. include <QtNetwork>

FortuneThread::FortuneThread(int socketDescriptor, const QString &fortune, QObject *parent)

   : QThread(parent), socketDescriptor(socketDescriptor), text(fortune)

{ }

void FortuneThread::run() {

   QTcpSocket tcpSocket;

   if (!tcpSocket.setSocketDescriptor(socketDescriptor)) {
       emit error(tcpSocket.error());
       return;
   }

   QByteArray block;
   QDataStream out(&block, QIODevice::WriteOnly);
   out.setVersion(QDataStream::Qt_4_0);
   out << (quint16)0;
   out << text;
   out.device()->seek(0);
   out << (quint16)(block.size() - sizeof(quint16));

   tcpSocket.write(block);
   tcpSocket.disconnectFromHost();
   tcpSocket.waitForDisconnected();

}


  1. include <QApplication>
  2. include <QtCore>
  3. include <stdlib.h>
  4. include "dialog.h"

int main(int argc, char *argv[]) {

   QApplication app(argc, argv);
   Dialog dialog;
   dialog.show();
   qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
   return dialog.exec();

}


 </source>