QtRemoteObjects ウェブソケットアプリケーション
QtRemoteObjects で、QIODevice-based でないトランスポート(QWebSocket)を使う。
この例では、QStandardItemModel
を Web ソケットで共有しています。モデルはwsserver
アプリケーションのウィンドウで編集することができ、その変更はwsclient
アプリケーションのウィンドウに反映されます。
これは、QWebSocket
用に小さなQIODevice 由来のラッパーWebSocketIoDevice
を実装することで可能になります。QtがSSLをサポートしてコンパイルされている場合、SSLが使用されます。
WsServerアプリケーション
wsserver
アプリケーションは2つのカラムを持つ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 The Qt Company Ltd. 本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。