QtRemoteObjects 웹소켓 애플리케이션
QtRemoteObjects 에서QIODevice 기반이 아닌 전송 방식(QWebSocket) 사용하기.
이 예제는 웹 소켓을 통해 QStandardItemModel 를 공유합니다. wsserver 애플리케이션의 창에서 모델을 편집할 수 있으며, 변경 사항은 wsclient 애플리케이션의 창으로 반영됩니다.
이는 QWebSocket 용 QIODevice 에서 파생된 작은 래퍼인 WebSocketIoDevice 을 구현함으로써 가능해집니다. Qt가 SSL 지원을 포함하도록 컴파일된 경우 SSL이 사용됩니다.

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 지원을 포함하도록 컴파일된 경우 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::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);
}
});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을 지원하도록 컴파일된 경우, 클라이언트는 SSL을 사용하도록 구성됩니다.
#ifndef QT_NO_SSL
// 가능한 경우 항상 보안 연결을 사용합니다
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그런 다음 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();© 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.