Fortune-Server
Zeigt, wie man einen Server für einen Netzwerkdienst erstellt.
Dieses Beispiel soll zusammen mit dem Fortune Client Beispiel oder dem Blocking Fortune Client Beispiel ausgeführt werden.
Es verwendet QTcpServer, um eingehende TCP-Verbindungen zu akzeptieren, und ein einfaches QDataStream -basiertes Datenübertragungsprotokoll, um ein Fortune an den verbindenden Client (aus dem Fortune-Client-Beispiel ) zu schreiben, bevor die Verbindung geschlossen wird.
class Server : public QDialog { Q_OBJECT public: explicit Server(QWidget *parent = nullptr); private slots: void sendFortune(); private: void initServer(); QLabel *statusLabel = nullptr; QTcpServer *tcpServer = nullptr; QList<QString> fortunes; };
Der Server wird mit einer einfachen Klasse mit nur einem Slot implementiert, um eingehende Verbindungen zu verarbeiten.
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; } QString ipAddress; const QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses(); // use the first non-localhost IPv4 address for (const QHostAddress &entry : ipAddressesList) { if (entry != QHostAddress::LocalHost && entry.toIPv4Address()) { ipAddress = entry.toString(); break; } } // if we did not find one, use IPv4 localhost if (ipAddress.isEmpty()) ipAddress = QHostAddress(QHostAddress::LocalHost).toString(); statusLabel->setText(tr("The server is running on\n\nIP: %1\nport: %2\n\n" "Run the Fortune Client example now.") .arg(ipAddress).arg(tcpServer->serverPort()));
In seinem Konstruktor ruft unser Server-Objekt QTcpServer::listen() auf, um eine QTcpServer einzurichten, die auf allen Adressen an einem beliebigen Port lauscht. In zeigt dann den gewählten Port QTcpServer in einem Label an, so dass der Benutzer weiß, mit welchem Port sich der Fortune-Client verbinden soll.
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.");
Unser Server generiert eine Liste mit zufälligen Glücksfällen, die er an die sich verbindenden Clients senden kann.
connect(tcpServer, &QTcpServer::newConnection, this, &Server::sendFortune);
Wenn ein Client eine Verbindung zu unserem Server herstellt, sendet QTcpServer QTcpServer::newConnection (). Dies wiederum ruft unseren sendFortune()-Slot auf:
void Server::sendFortune() { QByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_6_5); out << fortunes[QRandomGenerator::global()->bounded(fortunes.size())];
Der Zweck dieses Slots ist es, eine zufällige Zeile aus unserer Glücksliste auszuwählen, sie mit QDataStream in ein QByteArray zu kodieren und sie dann an den verbindenden Socket zu schreiben. Dies ist ein üblicher Weg, um binäre Daten mit QTcpSocket zu übertragen. Zuerst erstellen wir ein QByteArray und ein QDataStream Objekt, indem wir das Bytearray an den Konstruktor von QDataStream übergeben. Dann setzen wir die Protokollversion von QDataStream explizit auf QDataStream::Qt_5_10, um sicherzustellen, dass wir mit Clients aus zukünftigen Versionen von Qt kommunizieren können (siehe QDataStream::setVersion()). Wir fahren fort, indem wir ein zufälliges Vermögen einstreuen.
QTcpSocket *clientConnection = tcpServer->nextPendingConnection(); connect(clientConnection, &QAbstractSocket::disconnected, clientConnection, &QObject::deleteLater);
Anschließend rufen wir QTcpServer::nextPendingConnection() auf, das QTcpSocket zurückgibt, das die Serverseite der Verbindung darstellt. Indem wir QTcpSocket::disconnected() mit QObject::deleteLater() verbinden, stellen wir sicher, dass der Socket nach dem Trennen der Verbindung gelöscht wird.
clientConnection->write(block); clientConnection->disconnectFromHost(); }
Das kodierte Vermögen wird mit QTcpSocket::write() geschrieben, und schließlich rufen wir QTcpSocket::disconnectFromHost() auf, das die Verbindung schließt, nachdem QTcpSocket das Vermögen in das Netzwerk geschrieben hat. Da QTcpSocket asynchron arbeitet, werden die Daten geschrieben, nachdem diese Funktion zurückgekehrt ist, und die Kontrolle geht zurück an die Ereignisschleife von Qt. Der Socket wird dann geschlossen, was wiederum QObject::deleteLater() veranlasst, ihn zu löschen.
Siehe auch Fortune Client und Threaded Fortune Server.
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.