Remote Objects: Can't register Clients to Registry using a TCP-connection
-
So lately I have been trying out the functionalities of the Qt remoteobjects and wanted to establish a TCP connection between a Host Node and Client Nodes using a Registry for the Clients to register at the Host Node.
I therefore used the code provided in the official external schemas documentation: https://doc.qt.io/qt-5/qtremoteobjects-external-schemas.html and additionally enabled the remoting of the host node on the server side while I wanted to aquire the Replica object on the client side.
My Server Side Code:FileManager fileManager; const QUrl registryUrl = QUrl(QStringLiteral("tcp://serverIpAdressHere:65212")); const QUrl extUrl = QUrl(QStringLiteral("exttcp://serverIpAdressHere:65213")); QTcpServer tcpServer; tcpServer.listen(QHostAddress(extUrl.host()), extUrl.port()); QRemoteObjectRegistryHost registry(registryUrl); QRemoteObjectHost srcNode(extUrl, registryUrl, QRemoteObjectHost::AllowExternalRegistration); srcNode.enableRemoting(&fileManager); //Do work with fileManager
My Client Side Code:
const QUrl registryUrl = QUrl(QStringLiteral("tcp://serverIpAdressHere:65212")); QRemoteObjectNode repNode(registryUrl); QRemoteObjectNode::RemoteObjectSchemaHandler setupTcp = [&repNode](QUrl url) -> void { QTcpSocket *socket = new QTcpSocket(&repNode); QObject::connect(socket, &QTcpSocket::connected, [socket, &repNode]() -> void { qDebug() << "Added client side connection"; repNode.addClientSideConnection(socket); }); QObject::connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QSslSocket::error), [socket](QAbstractSocket::SocketError) -> void { qDebug() << "Deleted socket"; delete socket; }); qDebug() << "Connected to host with URL: " << url.host() <<":" << url.port(); socket->connectToHost(url.host(), url.port()); }; repNode.registerExternalSchema(QStringLiteral("exttcp"), setupTcp); QSharedPointer<QRemoteObjectReplica> ptr; ptr.reset(repNode.acquire<FileManagerReplica>()); Client client(ptr); //Do work with client
I created a .rep file for my FileManager class which simply sends some signals with file contents to the Client and wanted to connect each Client process to the corresponding Registry using the registryUrl.
Now my problem is that the TCP-connection seems to be established normally since the server side code approves a correct connection of the client to the provided QTcpServer (QTcpServer::newConnection() gets emitted), however the Client doesn't receive any of the file contents being provided to him using remoteobjects. Please note that the communication between the processes works fine with URLs using the local schema and therefore not using TCP. So the problem must appear in the actual registration of the clients to the registry using external schemas.
Does anyone see a problem with my code? Can't really figure out the problem since the way the TCP connection is established is the same as described in the documentation.Thank you very much!
-
Basically you missed to add addHostSideConnection on server side. Here is below code snippet.
// server side
void onNewServerConnection()
{
qDebug() << "onNewServerConnection";
bool newConn = false;
if(auto tcpServer = qobject_cast<QTcpServer*>(sender()))
{
while(tcpServer->hasPendingConnections())
{
newConn = true;
m_pHost->addHostSideConnection(tcpServer->nextPendingConnection());
}
}
}
// Use standard tcp url for the registry
const QUrl registryUrl = QUrl(QStringLiteral("tcp://127.0.0.1:65212"));
// Use "exttcp" for the "external" interface
const QUrl extUrl = QUrl(QStringLiteral("exttcp://127.0.0.1:65213"));// Create the server and listen outside of QtRO // QTcpServer tcpServer; auto tcpServer = new QTcpServer(this); auto host = extUrl.host(); // We only know how to handle tcp:// and local: bool res = false; res = tcpServer->listen(QHostAddress(extUrl.host()), extUrl.port()); if(res) { // m_servers.insert(url, server); connect(tcpServer, &QTcpServer::newConnection, this, &YourClass::onNewServerConnection); } else { qWarning().nospace() << "server could not listen on URL: " << extUrl.toString() << ". Error type: " << tcpServer->serverError() << ", message: " << tcpServer->errorString(); delete tcpServer; } // We need a registry for everyone to connect to QRemoteObjectRegistryHost registry(registryUrl); // Finally, we create our host node and register "exttcp" as our schema. // We need the AllowExternalRegistration parameter to prevent the node from // setting a hostUrlInvalid error. m_pHost = new QRemoteObjectHost(extUrl, registryUrl, QRemoteObjectHost::AllowExternalRegistration); // From now on, when we call enableRemoting() from this node, the registry // will be updated to show the Source object at extUrl.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
OnClient side
// Use standard tcp url for the registry
const QUrl registryUrl = QUrl(QStringLiteral("tcp://127.0.0.1:65212"));// This time create the node connected to the registry QRemoteObjectNode repNode(registryUrl); // Create the RemoteObjectSchemaHandler callback QRemoteObjectNode::RemoteObjectSchemaHandler setupTcp = [&repNode](QUrl url) -> void { QTcpSocket *socket = new QTcpSocket(&repNode); connect(socket, &QTcpSocket::connected, [socket, &repNode]() { qDebug() << "Added client side connection"; repNode.addClientSideConnection(socket); }); connect(socket, &QSslSocket::errorOccurred, [socket](QAbstractSocket::SocketError error) { qDebug() << "Deleted socket"; delete socket; }); qDebug() << "Connected to host with URL: " << url.host() <<":" << url.port(); socket->connectToHost(url.host(), url.port()); }; // Once we call registerExternalSchema, the above method will be called // whenever the registry sees an object we are interested in on "exttcp" repNode.registerExternalSchema(QStringLiteral("exttcp"), setupTcp); // local replica // QRemoteObjectNode repNode; // create remote object node // m_pHost = new QRemoteObjectHost(QUrl(ss.str().c_str())); // repNode.connectToNode(QUrl(ss.str().c_str())); //QUrl(QStringLiteral("local:replica"))); auto ptr = repNode.acquireDynamic("something");