SSL-Server und -Client
Einrichten eines sicheren Remote-Object-Netzwerks mit QSslSockets.
Die Verschlüsselung der Kommunikation ist unerlässlich, wenn Sie Daten über ein Netzwerk übertragen müssen, über das Sie keine vollständige Kontrolle haben. Die beiden Anwendungen in diesem Beispiel zeigen, wie Remote-Objekte über eine SSL-Verbindung gemeinsam genutzt werden und wie auf sie zugegriffen werden kann.

Sowohl „sslserver“ als auch „sslcppclient“ verwenden ein benutzerdefiniertes Root-CA-Zertifikat, um die Zertifikate des jeweils anderen zu validieren; diese befinden sich alle im Verzeichnis „sslserver/cert“.
SSL-Server
Der sslserver wird mit Zertifikaten und einem privaten Schlüssel konfiguriert.
auto config = QSslConfiguration::defaultConfiguration();
config.setCaCertificates(QSslCertificate::fromPath(QStringLiteral(":/sslcert/rootCA.pem")));
QFile certificateFile(QStringLiteral(":/sslcert/server.crt"));
if (certificateFile.open(QIODevice::ReadOnly | QIODevice::Text))
config.setLocalCertificate(QSslCertificate(certificateFile.readAll(), QSsl::Pem));
else
qFatal("Could not open certificate file");
QFile keyFile(QStringLiteral(":/sslcert/server.key"));
if (keyFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
QSslKey key(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
if (key.isNull())
qFatal("Key is not valid");
config.setPrivateKey(key);
} else {
qFatal("Could not open key file");
}
config.setPeerVerifyMode(QSslSocket::VerifyPeer);
QSslConfiguration::setDefaultConfiguration(config);Anschließend werden ein ` QRemoteObjectHost `-Objekt und ein ` QSslServer `-Objekt erstellt. Das ` QSslServer `-Objekt lauscht auf Port 65511. Dann wird die Methode `setHostUrl` für das ` QRemoteObjectHost `-Objekt mit der URL des ` QSslServer `-Objekts aufgerufen.
QRemoteObjectHost host;
QSslServer server;
server.listen(QHostAddress::Any, 65511);
host.setHostUrl(server.serverAddress().toString(), QRemoteObjectHost::AllowExternalRegistration);Ein Lambda-Ausdruck wird verwendet, um das Signal „errorOccurred“ zu verarbeiten, indem der Fehler im Terminal ausgegeben wird. Ein zweiter Lambda-Ausdruck ist mit dem Signal „pendingConnectionAvailable“ verbunden, das einen Fehlerbehandler anruft und die Methode „addHostSideConnection“ des Objekts „ QRemoteObjectHost “ mit dem eingehenden Socket als Argument aufruft, damit das Host-Objekt den Socket für die Kommunikation verwendet.
QObject::connect(&server, &QSslServer::errorOccurred,
[](QSslSocket*socket, QAbstractSocket::SocketErrorerror) {
Q_UNUSED(socket);
qDebug() << "QSslServer::errorOccurred" << error;
});
QObject::connect(&server, &QSslServer::pendingConnectionAvailable, [&server, &host]() {
qDebug() << "New connection available";
QSslSocket*socket = qobject_cast<QSslSocket*>(server.nextPendingConnection());
Q_ASSERT(socket);
QObject::connect(socket, &QSslSocket::errorOccurred,
[](QAbstractSocket::SocketErrorerror) {
qDebug() << "QSslSocket::error" << error;
});
host.addHostSideConnection(socket);
});Abschließend wird ein `MinuteTimer`-Objekt erstellt und die Methode `enableRemoting` wird für das ` QRemoteObjectHost `-Objekt mit dem `MinuteTimer`-Objekt als Argument aufgerufen, um dessen gemeinsame Nutzung zu ermöglichen.
MinuteTimer timer;
host.enableRemoting(&timer);SSL-Client
Der „sslcppclient“ legt das Stamm-CA-Zertifikat fest und erstellt anschließend ein „Tester“-Objekt.
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
auto config = QSslConfiguration::defaultConfiguration();
config.setCaCertificates(QSslCertificate::fromPath(QStringLiteral(":/sslcert/rootCA.pem")));
QSslConfiguration::setDefaultConfiguration(config);
Tester t;
return a.exec();
}Im Konstruktor von `Tester` wird ein temporäres ` QRemoteObjectNode `-Objekt erstellt, und mit `setupConnection` wird ein ` QSslSocket `-Objekt erstellt und konfiguriert. Ein Fehlerhandler wird angehängt, und das ` QSslSocket `-Objekt wird vom ` QRemoteObjectNode `-Objekt verwendet, indem die Methode `addClientSideConnection` aufgerufen wird.
QRemoteObjectNode m_client;
auto socket = setupConnection();
connect(socket, &QSslSocket::errorOccurred,
socket, [](QAbstractSocket::SocketErrorerror){
qDebug() << "QSslSocket::error" << error;
}) ;
m_client.addClientSideConnection(socket);Anschließend werden drei ` QScopedPointer `, die Mitglieder der Klasse `Tester` sind, mithilfe von `acquire` auf dem Objekt ` QRemoteObjectNode ` mit drei Replikaten von `MinuteTimer` verbunden. Schließlich wird ` QTimer::singleShot ` viermal verwendet, um nach einer Verzögerung den Befehl „reset“ aufzurufen.
ptr1.reset(m_client.acquire< MinuteTimerReplica >());
ptr2.reset(m_client.acquire< MinuteTimerReplica >());
ptr3.reset(m_client.acquire< MinuteTimerReplica >());
QTimer::singleShot(0, this, &Tester::clear);
QTimer::singleShot(1, this, &Tester::clear);
QTimer::singleShot(10000, this, &Tester::clear);
QTimer::singleShot(11000, this, &Tester::clear);Wenn „Tester::clear“ die ersten drei Male aufgerufen wird, wird jeweils für einen anderen Zeiger geprüft, ob dieser gebunden ist, und anschließend zurückgesetzt. Beim vierten Aufruf wird die Anwendung beendet.
void clear()
{
static int i = 0;
if (i== 0) {
i++;
if (ptr1.isNull())
qCritical() << "Pointer 1 was not set";
ptr1.reset();
} else if (i== 1) {
i++;
if (ptr2.isNull())
qCritical() << "Pointer 2 was not set";
ptr2.reset();
} else if (i== 2) {
i++;
if (ptr3.isNull())
qCritical() << "Pointer 3 was not set";
ptr3.reset();
} else {
qApp->quit();
}
}© 2026 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.