QtRemoteObjects WebSocket应用程序
使用非QIODevice基于的传输(QWebSocket)与QtRemoteObjects。
此示例通过WebSocket共享一个QStandardItemModel。该模型可以在wsserver应用程序的窗口中编辑,并且更改会传播到wsclient应用程序的窗口。
这是通过实现一个小型的QIODevice派生包装器,WebSocketIoDevice,为QWebSocket。
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 // Always use secure connections when available 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 // Always use secure connections when available 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();
© 2024 Qt公司。本文档中的文档贡献的版权属于其各自的拥有者。本提供的文档依据自由软件基金会发布的GNU自由文档许可证版本1.3的条款进行许可。Qt及相应的标志是Qt公司在芬兰及其它国家的商标。所有其他商标均为各自所有者的财产。