First attempt to use Qt networking on QML apps
-
What is ipAddress used for? You are not using it when you call listen().
ipAddress is used to store the list of local/non-local IP addresses. But I didn't understand the part "You are not using it when you call listen()".
But the actuall issue is that you have a return just before connect(), so connect() is never called..
Right. I moved the connect() to the part right after the listen(). Now the onNewConnection() slot is successfully called and it prints the message "OnNewConnection was called" in Application Output window as expected.
Now there's still a problem remaining!
This isclient.cpp
:#include "client.h" #include <QtNetwork> Client::Client(QObject *parent) : QObject{parent} , tcpSocket(new QTcpSocket(this)) { out.setDevice(tcpSocket); out.setVersion(QDataStream::Qt_4_0); } void Client::sendAddress(QString ip, QString port) { tcpSocket->abort(); tcpSocket->connectToHost(ip, port.toInt()); connect(tcpSocket, &QAbstractSocket::connected, []() { qDebug() << "Connected to the host"; }); } void Client::sendMessage(const QString& message) //called from front-end { QByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_5_10); out << message; tcpSocket->write(block); }
The sendAddress slot prints the message of the lambda in output ("Connected to the host") so by that I assume the connection between the client and server the way above is properly established. The remaining problem is that the sendMessage slot still doesn't send its message (its string parameter) to the sever! :(
@qcoderpro said in First attempt to use Qt networking on QML apps:
But I didn't understand the part "You are not using it when you call listen()".
You know that you can pass an IP to listen? See https://doc.qt.io/qt-5/qtcpserver.html#listen
Where and when do you call sendMessage ?
You also should add code for error handling: https://doc.qt.io/qt-5/qabstractsocket.html#errorOccurred
https://doc.qt.io/qt-5/qiodevice.html#errorString -
@qcoderpro said in First attempt to use Qt networking on QML apps:
But I didn't understand the part "You are not using it when you call listen()".
You know that you can pass an IP to listen? See https://doc.qt.io/qt-5/qtcpserver.html#listen
Where and when do you call sendMessage ?
You also should add code for error handling: https://doc.qt.io/qt-5/qabstractsocket.html#errorOccurred
https://doc.qt.io/qt-5/qiodevice.html#errorStringwrote on 6 Apr 2022, 17:51 last edited by qcoderpro 4 Jun 2022, 18:14You know that you can pass an IP to listen? See https://doc.qt.io/qt-5/qtcpserver.html#listen
No, I didn't know that and if I use listen() that way I need to someway convert the ipAddress which a QString to a QHostAddress. But now the connection is properly established and the connect(...) calls the slot onNewConnection.
Where and when do you call sendMessage ?
In the front-end:
ColumnLayout { anchors.fill: parent TextField { id: ipAddrs } TextField { id: portNum } Button { text: "Send Address" onClicked: myObj.sendAddress(ipAddrs.text.toString(), portNum.text.toString()) } RowLayout { Layout.alignment: Qt.AlignBottom TextField { id: txtField Layout.fillWidth: true } Button { text: qsTr("Send") onClicked: myObj.sendMessage(txtField.text) } } } MyClass { id: myObj }
You also should add code for error handling: https://doc.qt.io/qt-5/qabstractsocket.html#errorOccurred
https://doc.qt.io/qt-5/qiodevice.html#errorStringFor that, I added this connect() after the lambda in client.cpp:
connect(tcpSocket, &QAbstractSocket::errorOccurred, this, &Client::displayError);
and this slot there:void Client::displayError(QAbstractSocket::SocketError socketError) { // for this stage, printing the error messages using qDenug will be fine switch (socketError) { case QAbstractSocket::RemoteHostClosedError: break; case QAbstractSocket::HostNotFoundError: qDebug() <<"The host was not found. Please check the " "host name and port settings."; break; case QAbstractSocket::ConnectionRefusedError: qDebug() << "The connection was refused by the peer. " "Make sure the server is running, " "and check that the host name and port " "settings are correct."; break; default: qDebug() << "The following error occurred: " + tcpSocket->errorString(); } }
Still no message is sent nor there's any error.
-
You know that you can pass an IP to listen? See https://doc.qt.io/qt-5/qtcpserver.html#listen
No, I didn't know that and if I use listen() that way I need to someway convert the ipAddress which a QString to a QHostAddress. But now the connection is properly established and the connect(...) calls the slot onNewConnection.
Where and when do you call sendMessage ?
In the front-end:
ColumnLayout { anchors.fill: parent TextField { id: ipAddrs } TextField { id: portNum } Button { text: "Send Address" onClicked: myObj.sendAddress(ipAddrs.text.toString(), portNum.text.toString()) } RowLayout { Layout.alignment: Qt.AlignBottom TextField { id: txtField Layout.fillWidth: true } Button { text: qsTr("Send") onClicked: myObj.sendMessage(txtField.text) } } } MyClass { id: myObj }
You also should add code for error handling: https://doc.qt.io/qt-5/qabstractsocket.html#errorOccurred
https://doc.qt.io/qt-5/qiodevice.html#errorStringFor that, I added this connect() after the lambda in client.cpp:
connect(tcpSocket, &QAbstractSocket::errorOccurred, this, &Client::displayError);
and this slot there:void Client::displayError(QAbstractSocket::SocketError socketError) { // for this stage, printing the error messages using qDenug will be fine switch (socketError) { case QAbstractSocket::RemoteHostClosedError: break; case QAbstractSocket::HostNotFoundError: qDebug() <<"The host was not found. Please check the " "host name and port settings."; break; case QAbstractSocket::ConnectionRefusedError: qDebug() << "The connection was refused by the peer. " "Make sure the server is running, " "and check that the host name and port " "settings are correct."; break; default: qDebug() << "The following error occurred: " + tcpSocket->errorString(); } }
Still no message is sent nor there's any error.
@qcoderpro said in First attempt to use Qt networking on QML apps:
For that, I added this connect() after the lambda in client.cpp:
The idea was actually to check the errors on server side
-
@qcoderpro said in First attempt to use Qt networking on QML apps:
For that, I added this connect() after the lambda in client.cpp:
The idea was actually to check the errors on server side
wrote on 7 Apr 2022, 08:09 last edited by@jsulm
Yeah, right.
I declared a QTcpSocket object in the server app and added the connect() and displayError slot as mentioned above in it. As before, the connection is established but no message is sent nor is an error displayed!
I shared both projects in a zip file in link below. If you have time, take a look at them please. I'm sure the remaining problem will be clear to you. I tried to keep the projects as simple as possible just to do the job: https://www.4shared.com/s/f_Gct6Kjwiq -
This file sharing is unusable without account it seems.
If you want to share multiple files, using https://gist.github.com would be better for the people that want to help you.
-
This file sharing is unusable without account it seems.
If you want to share multiple files, using https://gist.github.com would be better for the people that want to help you.
wrote on 7 Apr 2022, 14:54 last edited by@GrecKo
That's a code sharing platform (instead of files) but if code is meant to be easier than the projects both in a zip file then as usual it's feasible to share them here.
server.h
:#include <QObject> #include <QAbstractSocket> class QTcpServer; class QTcpSocket; class Server : public QObject { Q_OBJECT public: explicit Server(QObject *parent = nullptr); public slots: QString initServer(); void setMessage(); QString getMessage() const; void onNewConnection(); void displayError(QAbstractSocket::SocketError); private: QTcpServer* tcpServer { nullptr }; QTcpSocket* tcpSocket { nullptr }; QDataStream in; QString message; };
server.cpp
:#include "server.h" #include <QtNetwork> #include <QtCore> Server::Server(QObject *parent) : QObject{parent} , tcpServer(new QTcpServer(this)) , tcpSocket(new QTcpSocket(this)) { } QString Server::initServer() { // Called from the front-end tcpServer = new QTcpServer(this); if(!tcpServer->listen()) return "Server Unable to start the server: " + tcpServer->errorString(); connect(tcpServer, &QTcpServer::newConnection, this, &Server::onNewConnection); connect(tcpSocket, &QAbstractSocket::errorOccurred, this, &Server::displayError); QString ipAddress; QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses(); // use the first non-local IPv4 address for(int i=0; i<ipAddressesList.size(); ++i) if(ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address()) { ipAddress = ipAddressesList.at(i).toString(); break; } // if we did not find one, use IPv4 localhost if(ipAddress.isEmpty()) ipAddress = QHostAddress(QHostAddress::LocalHost).toString(); return " The server is running on\n\n IP: " + ipAddress + "\n port: " + QString::number(tcpServer->serverPort()) + "\n\n Run the Client example now."; } void Server::onNewConnection() { qDebug() << "OnNewConnection was called!\n"; QTcpSocket *clientConnection = tcpServer->nextPendingConnection(); connect(clientConnection, &QAbstractSocket::disconnected, clientConnection, &QObject::deleteLater); in.setDevice(clientConnection); in.setVersion(QDataStream::Qt_4_0); connect(clientConnection, &QAbstractSocket::readyRead, this, &Server::setMessage); } void Server::displayError(QAbstractSocket::SocketError socketError) { // for this stage, printing the error messages using qDenug will be fine switch (socketError) { case QAbstractSocket::RemoteHostClosedError: break; case QAbstractSocket::HostNotFoundError: qDebug() <<"The host was not found. Please check the " "host name and port settings."; break; case QAbstractSocket::ConnectionRefusedError: qDebug() << "The connection was refused by the peer. " "Make sure the server is running, " "and check that the host name and port " "settings are correct."; break; default: qDebug() << "The following error occurred: " + tcpSocket->errorString(); } } void Server::setMessage() { in.startTransaction(); QString msg; in >> msg; if (!in.commitTransaction()) message = "commitTransaction error" ; else message = msg; } QString Server::getMessage() const { return message; }
server's project qml file
:import QtQuick import QtQuick.Controls import QtQuick.Layouts import SomeClass 1.0 Window { width: 300 height: 200 visible: true title: qsTr("Server") color: "lightblue" ColumnLayout { anchors.fill: parent Label { text: myObj.initServer() } Label { id: msgLabel text: myObj.getMessage() } } MyClass { id: myObj } }
client.h
:#include <QDataStream> #include <QObject> class QTcpSocket; class Client : public QObject { Q_OBJECT public: explicit Client(QObject *parent = nullptr); public slots: void sendAddress(QString, QString); void sendMessage(const QString&); private: QTcpSocket* tcpSocket { nullptr }; QDataStream out; };
client.cpp
:#include "client.h" #include <QtNetwork> Client::Client(QObject *parent) : QObject{parent} , tcpSocket(new QTcpSocket(this)) { out.setDevice(tcpSocket); out.setVersion(QDataStream::Qt_4_0); } void Client::sendAddress(QString ip, QString port) { tcpSocket->abort(); tcpSocket->connectToHost(ip, port.toInt()); connect(tcpSocket, &QAbstractSocket::connected, []() { qDebug() << "Connected to the host"; }); } void Client::sendMessage(const QString& message) { //called from front-end QByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_5_10); out << message; tcpSocket->write(block); }
client's project qml file
:import QtQuick import QtQuick.Controls import QtQuick.Layouts import SomeClass 1.0 Window { width: 300 height: 200 visible: true title: qsTr("Client") color: "lightblue" ColumnLayout { anchors.fill: parent TextField { id: ipAddrs } TextField { id: portNum } Button { text: "Send Address" onClicked: myObj.sendAddress(ipAddrs.text.toString(), portNum.text.toString()) } RowLayout { Layout.alignment: Qt.AlignBottom TextField { id: txtField Layout.fillWidth: true } Button { text: qsTr("Send") onClicked: myObj.sendMessage(txtField.text) } } } MyClass { id: myObj } }
Hopefully we can now find the issue. :(
-
wrote on 7 Apr 2022, 15:02 last edited by
Here is also the link for that platform embracing the files code: https://gist.github.com/Tomtesty/eff99a9721afa7a44558fe097e65b079
-
wrote on 9 Apr 2022, 12:58 last edited by
Is the problem still ambiguous, please? I tried hard but can't find the issue. :(
21/28