Sur cette page

Applications WebSockets avec QtRemoteObjects

Utilisation d'un protocole de transport autre qu'QIODevice(QWebSocket) avec QtRemoteObjects.

Cet exemple partage un objet « QStandardItemModel » via un WebSocket. Le modèle peut être modifié dans la fenêtre de l’application wsserver, et les modifications sont répercutées dans la fenêtre de l’application wsclient.

Ceci est rendu possible grâce à l’implémentation d’un petit wrapper dérivé de ` QIODevice`, ` WebSocketIoDevice`, pour ` QWebSocket`. Le protocole SSL est utilisé si Qt a été compilé avec la prise en charge de ce protocole.

Fenêtre SourceView avec un tableau à deux colonnes et mise en évidence des lignes par des couleurs

L'application WsServer

L'application wsserver crée un QStandardItemModel comportant deux colonnes et y insère des données.

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

Elle démarre ensuite un serveur QWebSocketServer lié au port 8088 et héberge le modèle de données.

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

Lors de la gestion des nouvelles connexions, le protocole SSL est configuré si Qt a été compilé avec la prise en charge de ce protocole. Une instance de ` WebSocketIoDevice ` est ensuite créée à partir de la connexion WebSocketServer entrante.

    QObject::connect(&webSockServer,&QWebSocketServer::newConnection, &hostNode, [&hostNode, &webSockServer]{
        while (auto conn = webSockServer.nextPendingConnection()) {
#ifndef QT_NO_SSL
            // Toujours utiliser des connexions sécurisées lorsqu’elles sont disponibles
            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);
        }
    });

Un QTreeView est créé avec le QStandardItemModel comme modèle. Ensuite, plusieurs minuteurs sont lancés à l'aide de ` QTimer::singleShot ` afin d'effectuer d'autres modifications sur le modèle.

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

L'application WsClient

L'application « wsclient » crée un QWebSocket et un WebSocketIoDevice en le prenant comme argument.

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

Si Qt est compilé avec la prise en charge de SSL, le client est configuré en conséquence.

#ifndef QT_NO_SSL
    // Toujours utiliser des connexions sécurisées lorsqu'elles sont disponibles
    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

Ensuite, un objet ` QRemoteObjectNode ` est créé et configuré pour utiliser le `WebSocketIoDevice`. Il se connecte ensuite à wsserver.

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

Un QTreeView est créé pour afficher les données provenant du serveur. Le modèle est récupéré à partir du nœud, puis défini comme modèle du QTreeView, qui s’affiche alors.

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

Exemple de projet sur code.qt.io

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