Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to use QtRemoteObjects in order to remote duplicate a model



  • Hello guys,

    I would like to know how to use QtRemoteObjects in order to synchronize a QAbstractItemModel (or QStandardItemModel) from a server into many clients over QTcpSocket (or better QSslSocket).
    The clients can setData on the model and all other clients received the modification with dataChanged. All clients can also call data on the model.

    Is it possible to create a simple sample to do that ?

    Thank you guys !



  • I tried to do my own sample and I have two errors, one client side and the other one server side.

    Here is the server code :

    #include <QtWidgets/QApplication>
    #include <QtNetwork/QTcpServer>
    #include <QtNetwork/QSslSocket>
    #include <QtNetwork/QSslKey>
    #include <QtRemoteObjects/QRemoteObjectHost>
    #include <QtGui/QStandardItemModel>
    #include <QtCore/QFile>
    
    int main(int argc, char *argv[])
    {
    	QApplication app(argc, argv);
    
    	QRemoteObjectHost srcNode;
    	QStandardItemModel model;
    
    	QTcpServer tcpServer;
    	QObject::connect(&tcpServer, &QTcpServer::newConnection, [&srcNode, &tcpServer]()
    	{
    		int descriptor = tcpServer.nextPendingConnection()->socketDescriptor();
    		QSslSocket* socket = new QSslSocket();
    		if (!socket->setSocketDescriptor(descriptor))
    		{
    			delete socket;
    			return;
    		}
    		QFile fileKey(":/Test/server-key.pem");
    		QFile fileCert(":/Test/server-crt.pem");
    		fileKey.open(QIODevice::ReadOnly);
    		fileCert.open(QIODevice::ReadOnly);
    		QSslKey key(&fileKey, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, "test");
    		QSslCertificate cert(&fileCert);
    		fileKey.close();
    		fileCert.close();
    		socket->setPrivateKey(key);
    		socket->addCaCertificates(QSslCertificate::fromPath(":/ServerLauncher/ca.pem"));
    		socket->setLocalCertificate(cert);
    		socket->setPeerVerifyMode(QSslSocket::VerifyNone);
    		socket->ignoreSslErrors();
    		socket->startServerEncryption();
    		srcNode.addHostSideConnection(socket);
    
    		QObject::connect(socket, &QAbstractSocket::disconnected, socket, &QObject::deleteLater);
    		QObject::connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QSslSocket::error), [socket](QAbstractSocket::SocketError error)
    		{
    			qDebug() << error;
    		});
    	});
    
    	srcNode.enableRemoting(&model, QStringLiteral("TestModel"));
    	
    	tcpServer.listen(QHostAddress::Any, 65213);
    
    	for (int n = 0; n < 500; ++n)
    	{
    		model.appendRow(QList<QStandardItem*>() << new QStandardItem(QString("%1").arg(n)));
    	}
    
    	return app.exec();
    }
    

    Here is the client code :

    #include <QtWidgets/QApplication>
    #include <QtNetwork/QSslSocket>
    #include <QtNetwork/QSslKey>
    #include <QtRemoteObjects/QRemoteObjectNode>
    #include <QtRemoteObjects/QAbstractItemModelReplica>
    #include <QtGui/QStandardItemModel>
    #include <QtCore/QFile>
    #include <QtWidgets/QTreeView>
    
    int main(int argc, char *argv[])
    {
    	QApplication app(argc, argv);
    
    	QTreeView view;
    	view.setWindowTitle(QStringLiteral("RemoteView"));
    	view.resize(640, 480);
    
    	QRemoteObjectNode repNode;
    	repNode.setHeartbeatInterval(1000);
    	QSslSocket socket(&repNode);
    	QObject::connect(&socket, &QSslSocket::connected, [&socket, &repNode, &view]()
    	{
    		socket.startClientEncryption();
    		repNode.addClientSideConnection(&socket);
    
    		QScopedPointer<QAbstractItemModelReplica> model(repNode.acquireModel(QStringLiteral("TestModel")));
    		view.setModel(model.data());
    	});
    	QFile fileKey(":/Test/client-key.pem");
    	QFile fileCert(":/Test/client-crt.pem");
    	fileKey.open(QIODevice::ReadOnly);
    	fileCert.open(QIODevice::ReadOnly);
    	QSslKey key(&fileKey, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, "test");
    	QSslCertificate cert(&fileCert);
    	fileKey.close();
    	fileCert.close();
    	socket.setPrivateKey(key);
    	socket.addCaCertificates(QSslCertificate::fromPath(":/Test/ca.pem"));
    	socket.setLocalCertificate(cert);
    	socket.setPeerVerifyMode(QSslSocket::VerifyNone);
    	socket.ignoreSslErrors();
    	socket.connectToHostEncrypted("127.0.0.1", 65213);
    
    	view.show();
    
    	return app.exec();
    }
    

    The error I have server side is : "QSocketNotifier: Multiple socket notifiers for same socket 876 and type Read".
    The error I have client side is : "qt.network.ssl: QSslSocket::startClientEncryption: cannot start handshake on non-plain connection".

    The Qt version I am using is 5.12.4.

    Nothing is displayed in the window client side.
    Do you know what are the problems with this code ?

    Thank you guys !


Log in to reply