QtRemoteObjects WebSockets-Anwendungen

Verwendung eines nichtQIODevice-basierten Transports (QWebSocket) mit QtRemoteObjects.

In diesem Beispiel wird ein QStandardItemModel über einen WebSocket freigegeben. Das Modell kann im Fenster der wsserver Anwendung bearbeitet werden, und die Änderungen werden an das Fenster der wsclient Anwendung weitergegeben.

Dies wird durch die Implementierung eines kleinen, von QIODevice abgeleiteten Wrappers, WebSocketIoDevice, für QWebSocket ermöglicht. SSL wird verwendet, wenn Qt mit Unterstützung dafür kompiliert ist.

Die WsServer-Anwendung

Die Anwendung wsserver erstellt eine QStandardItemModel mit zwei Spalten und fügt Daten in diese ein.

int main(int argc, char *argv[])
{
    QLoggingCategory::setFilterRules("qt.remoteobjects.debug=false\n"
                                     "qt.remoteobjects.warning=false");
    QApplication app(argc, argv);

    const int modelSize = 100000;
    QStringList list;
    QStandardItemModel sourceModel;
    QStringList hHeaderList;
    hHeaderList << QStringLiteral("First Column with spacing") << QStringLiteral("Second Column with spacing");
    sourceModel.setHorizontalHeaderLabels(hHeaderList);
    list.reserve(modelSize);
    for (int i = 0; i < modelSize; ++i) {
        QStandardItem *firstItem = new QStandardItem(QStringLiteral("FancyTextNumber %1").arg(i));
        if (i == 0)
            firstItem->appendRow(addChild(2, 2));
        QStandardItem *secondItem = new QStandardItem(QStringLiteral("FancyRow2TextNumber %1").arg(i));
        if (i % 2 == 0)
            firstItem->setBackground(Qt::red);
        QList<QStandardItem*> row;
        row << firstItem << secondItem;
        sourceModel.invisibleRootItem()->appendRow(row);
        //sourceModel.appendRow(row);
        list << QStringLiteral("FancyTextNumber %1").arg(i);
    }

Anschließend wird ein QWebSocketServer gestartet, das an Port 8088 gebunden ist und das Datenmodell hostet.

QWebSocketServer webSockServer{QStringLiteral("WS QtRO"), QWebSocketServer::NonSecureMode};
webSockServer.listen(QHostAddress::Any, 8088);

QRemoteObjectHost hostNode;
hostNode.setHostUrl(webSockServer.serverAddress().toString(), QRemoteObjectHost::AllowExternalRegistration);

hostNode.enableRemoting(&sourceModel, QStringLiteral("RemoteModel"), roles);

Bei der Verarbeitung neuer Verbindungen wird SSL konfiguriert, wenn Qt mit Unterstützung dafür kompiliert wurde. Dann wird eine WebSocketIoDevice unter Verwendung der eingehenden WebSocketServer-Verbindung erstellt.

QObject::connect(&webSockServer, &QWebSocketServer::newConnection, &hostNode, [&hostNode, &webSockServer]{ while(auto conn = webSockServer.nextPendingConnection()) {#ifndef QT_NO_SSL // Immer sichere Verbindungen verwenden, wenn verfügbar       QSslConfiguration sslConf;        QFile certFile(QStringLiteral(":/sslcert/server.crt")); if (!certFile.open(QIODevice::ReadOnly))            qFatal("Can't open client.crt file");
        sslConf.setLocalCertificate(QSslCertificate{certFile.readAll()});        QFile keyFile(QStringLiteral(":/sslcert/server.key")); if (!keyFile.open(QIODevice::ReadOnly))            qFatal("Can't open client.key file");
        sslConf.setPrivateKey(QSslKey{keyFile.readAll(), QSsl::Rsa}); sslConf.setPeerVerifyMode(QSslSocket::VerifyPeer);  conn->setSslConfiguration(sslConf);        QObject::connect(conn, &QWebSocket::sslErrors, conn, &QWebSocket::deleteLater);#endif     QObject::connect(conn, &QWebSocket::disconnected, conn, &QWebSocket::deleteLater);        QObject::connect(conn, &QWebSocket::errorOccurred, conn, &QWebSocket::deleteLater); auto ioDevice = new WebSocketIoDevice(conn);        QObject::connect(conn, &QWebSocket::destroyed, ioDevice, &WebSocketIoDevice::deleteLater); hostNode.addHostSideConnection(ioDevice); } });

Ein QTreeView wird mit dem QStandardItemModel als Modell erstellt. Dann werden mehrere Timer mit QTimer::singleShot gestartet, um weitere Änderungen am Modell vorzunehmen.

QTreeView view;
view.setWindowTitle(QStringLiteral("SourceView"));
view.setModel(&sourceModel);
view.show();
TimerHandler handler;
handler.model = &sourceModel;
QTimer::singleShot(5000, &handler, &TimerHandler::changeData);
QTimer::singleShot(10000, &handler, &TimerHandler::insertData);
QTimer::singleShot(11000, &handler, &TimerHandler::changeFlags);
QTimer::singleShot(12000, &handler, &TimerHandler::removeData);
QTimer::singleShot(13000, &handler, &TimerHandler::moveData);

return app.exec();

Die WsClient-Anwendung

Die Anwendung wsclient erstellt einen QWebSocket und eine WebSocketIoDevice, die sie als Argument nimmt.

QScopedPointer<QWebSocket> webSocket{new QWebSocket};
WebSocketIoDevice socket(webSocket.data());

Wenn Qt mit Unterstützung für SSL kompiliert ist, wird der Client damit konfiguriert.

#ifndef QT_NO_SSL // Immer sichere Verbindungen verwenden, wenn verfügbar   QSslConfiguration sslConf;    QFile certFile(QStringLiteral(":/sslcert/client.crt")); if (!certFile.open(QIODevice::ReadOnly))        qFatal("Can't open client.crt file");
    sslConf.setLocalCertificate(QSslCertificate{certFile.readAll()});    QFile keyFile(QStringLiteral(":/sslcert/client.key")); if (!keyFile.open(QIODevice::ReadOnly))        qFatal("Can't open client.key file");
    sslConf.setPrivateKey(QSslKey{keyFile.readAll(), QSsl::Rsa}); sslConf.setPeerVerifyMode(QSslSocket::VerifyPeer);  webSocket->setSslConfiguration(sslConf);#endif

Dann wird ein QRemoteObjectNode erstellt und für die Verwendung des WebSocketIoDevice eingerichtet. Dann wird eine Verbindung zu wsserver hergestellt.

QRemoteObjectNode node;
node.addClientSideConnection(&socket);
node.setHeartbeatInterval(1000);
webSocket->open(QStringLiteral("ws://localhost:8088"));

Ein QTreeView wird erstellt, um die Daten vom Server anzuzeigen. Das Modell wird vom Knoten erfasst und dann als Modell der QTreeView festgelegt, die dann angezeigt wird.

QTreeView view;
view.setWindowTitle(QStringLiteral("RemoteView"));
view.resize(640,480);
QScopedPointer<QAbstractItemModelReplica> model(node.acquireModel(QStringLiteral("RemoteModel")));
view.setModel(model.data());
view.show();

return app.exec();

Beispielprojekt @ code.qt.io

© 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.