QtRemoteObjects 웹 소켓 애플리케이션

QtRemoteObjects 과 함께QIODevice 기반이 아닌 전송(QWebSocket) 사용.

이 예는 웹 소켓을 통해 QStandardItemModel 을 공유합니다. wsserver 애플리케이션의 창에서 모델을 편집할 수 있으며, 변경 사항은 wsclient 애플리케이션의 창으로 전파됩니다.

이는 QWebSocket 에 대해 작은 QIODevice 파생 래퍼인 WebSocketIoDevice 을 구현함으로써 가능합니다. SSL은 Qt가 이를 지원하여 컴파일된 경우 사용됩니다.

WsServer 애플리케이션

wsserver 애플리케이션은 두 개의 열이 있는 QStandardItemModel 을 생성하고 여기에 데이터를 삽입합니다.

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

그런 다음 포트 8088에 바인딩된 QWebSocketServer 을 시작하고 데이터 모델을 호스팅합니다.

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

새 연결을 처리할 때 Qt가 이를 지원하도록 컴파일된 경우 SSL이 구성됩니다. 그런 다음 들어오는 WebSocketServer 연결을 사용하여 WebSocketIoDevice 이 생성됩니다.

QObject::connect(&webSockServer, &QWebSocketServer::newConnection, &hostNode, [&hostNode, &webSockServer]{ while(auto conn = webSockServer.nextPendingConnection()) {#ifndef QT_NO_SSL // 가능한 경우 항상 보안 연결 사용     QSslConfiguration sslConf;        QFile certFile(QStringLiteral(":/sslcert/server.crt")); if (!certFile.open(QIODevice::읽기 전용))            qFatal("Can't open client.crt file");
        sslConf.setLocalCertificate(QSslCertificate{certFile.readAll()});        QFile keyFile(QStringLiteral(":/sslcert/server.key")); if (!keyFile.open(QIODevice::읽기 전용))            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); } });

QStandardItemModel을 모델로 하여 QTreeView가 생성됩니다. 그런 다음 QTimer::singleShot 으로 여러 타이머를 시작하여 모델에 대한 추가 수정을 수행합니다.

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

WsClient 애플리케이션

wsclient 애플리케이션은 QWebSocket과 이를 인수로 받는 WebSocketIoDevice 을 생성합니다.

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

Qt가 SSL을 지원하여 컴파일된 경우 클라이언트는 이를 사용하여 구성됩니다.

#ifndef QT_NO_SSL // 가능한 경우 항상 보안 연결 사용   QSslConfiguration sslConf;    QFile certFile(QStringLiteral(":/sslcert/client.crt")); if (!certFile.open(QIODevice::읽기 전용))        qFatal("Can't open client.crt file");
    sslConf.setLocalCertificate(QSslCertificate{certFile.readAll()});    QFile keyFile(QStringLiteral(":/sslcert/client.key")); if (!keyFile.open(QIODevice::읽기 전용))        qFatal("Can't open client.key file");
    sslConf.setPrivateKey(QSslKey{keyFile.readAll(), QSsl::Rsa}); sslConf.setPeerVerifyMode(QSslSocket::VerifyPeer);  webSocket->setSslConfiguration(sslConf);#endif

그런 다음 QRemoteObjectNode 을 생성하고 WebSocketIoDevice를 사용하도록 설정합니다. 그런 다음 wsserver 에 연결합니다.

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

서버의 데이터를 표시하기 위해 QTreeView가 생성됩니다. 노드에서 모델을 가져온 다음 QTreeView의 모델로 설정하여 표시합니다.

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

예제 프로젝트 @ 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.