Solved QTcpSocket / QTcpServer, connection closed
-
@KroMignon , I'm starting to think the problem is not source code related but another factor. In the example I am looking at FortuneServer there is a fundamental difference. It gets the port to use automatically, where as in my code I am using a specific port 8123.
I've got the source to both FortuneServer and my own side by side and FortuneServer is much simpler in that it only implements one signal from QTcpServer "newConnection".
When a new client connection in the FortuneServer occurs it calls in the sendFortune slot:
QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
The difference is that the clientConnection status of isOpen is true, where as in my own slot, it's false.
In my slot that is called on a new Connection:
void clsSocketServer::sayHello() { clsSocketClient* pClient = new clsSocketClient(nextPendingConnection()); if ( pClient != nullptr ) { //Construct the message to send QJsonObject objMsg; objMsg.insert(clsJSON::mscszModule, clsMainWnd::mscstrTitle); pClient->sendJSON(objMsg); } }
In the function sendJSON:
void clsSocketClient::sendJSON(QJsonObject& objJSON) { //Associate this TCP socket with the output data stream QByteArray arybytMsg; QDataStream dsOut(&arybytMsg, QIODevice::WriteOnly); dsOut.setVersion(clsJSON::mscintQtVersion); //Send message to data stream dsOut << QJsonDocument(objJSON).toJson(QJsonDocument::Compact); //Write message qint64 int64Written = write(arybytMsg); //Make sure the data is written now flush(); qdbg() << "sendJSON: " << int64Written; }
The call to flush was just to ensure that the written content is not held in a buffer instead of calling disconnect, because I want the connection to remain open. But "int64Written" is -1 and I see in the "Application Output":
device not open
[Edit] Observing something odd...in my constructor for clsSocketClient I output:
qdbg() << __FILE__ << "," << __LINE__ << ",isOpen: " << pClient->isOpen();
This results in:
D00000000000000000020:../clsSocketClient.cpp,28,isOpen: true
Ignore the D number thats just my own message prefix, 28 is the line number, the at this point the socket is open. Then when it returns from the constructor and calls the function sendJSON:
void clsSocketClient::sendJSON(QJsonObject& objJSON) { //Associate this TCP socket with the output data stream QByteArray arybytMsg; QDataStream dsOut(&arybytMsg, QIODevice::WriteOnly); dsOut.setVersion(clsJSON::mscintQtVersion); //Send message to data stream dsOut << QJsonDocument(objJSON).toJson(QJsonDocument::Compact); //Write message qint64 int64Written = write(arybytMsg); //Make sure the data is written now flush(); //disconnectFromHost(); //Is this required? qdbg() << "sendJSON: " << int64Written; }
The "Application Output" shows:
W00000000000000000022:QIODevice::write (clsSocketClient): device not open D00000000000000000023:sendJSON: -1
-
@SPlatten No this cannot work.
As far as I can understand your code
clsSocketClient
is as subclass ofQTcpSocket
.
So simple C++ error:auto pClient = new clsSocketClient(nextPendingConnection());
is calling QTcpSocket copy constructoris using the QTcpSocket as parent.One solution would be to use
incomingConnection
to create the instance and save it in the queue:/** * @brief clsSocketService::incomingConnection * @param sfd : Client Socket Descriptor */ void clsSocketServer::incomingConnection(qintptr sfd) { auto pClient = new clsSocketClient(this); pClient->setSocketDescriptor(sfd); addPendingConnection(pClient); }
And then:
void clsSocketServer::sayHello() { auto pClient = qobject_cast<clsSocketClient*>(nextPendingConnection()); if ( pClient != nullptr ) { //Construct the message to send QJsonObject objMsg; objMsg.insert(clsJSON::mscszModule, clsMainWnd::mscstrTitle); pClient->sendJSON(objMsg); } }
-
@KroMignon, thank you, for some reason I'm having some problems with the line:
clsSocketClient* pClient = new clsSocketClient(this);
no matching constructor for initialization of 'clsSocketClient', the header is present, I've even tried changing the constructor to expect QAbstractSocket*, still the same.
-
@SPlatten said in QTcpSocket / QTcpServer, connection closed:
clsSocketClient
How does its constructors look like?
-
@SPlatten said in QTcpSocket / QTcpServer, connection closed:
no matching constructor for initialization of 'clsSocketClient', the header is present, I've even tried changing the constructor to expect QAbstractSocket*, still the same.
I don't know what
clsSocketClient
is.
I supposed it was:class clsSocketClient : public QTcpSocket { Q_OBJECT .... };
-
@KroMignon , clsSocketClient:
class clsSocketClient : public QTcpSocket { Q_OBJECT public: explicit clsSocketClient(QTcpSocket* pClient = nullptr); ...
Implementation:
clsSocketClient::clsSocketClient(QTcpSocket* pClient) : QTcpSocket(pClient) { QObject::connect(this, &QTcpSocket::connected, this, &clsSocketClient::onConnected); QObject::connect(this, &QTcpSocket::bytesWritten, this, &clsSocketClient::onBytesWritten); QObject::connect(this, &QTcpSocket::disconnected, this, &QObject::deleteLater); QObject::connect(this, &QTcpSocket::disconnected, this, &clsSocketClient::onDisconnected); QObject::connect(this, &QTcpSocket::errorOccurred, this, &clsSocketClient::onErrorOccurred); QObject::connect(this, &QTcpSocket::readyRead, this, &clsSocketClient::onDataIn); QObject::connect(this, &QTcpSocket::stateChanged, this, &clsSocketClient::onStateChanged); }
-
@SPlatten said in QTcpSocket / QTcpServer, connection closed:
explicit clsSocketClient(QTcpSocket* pClient = nullptr);
I guess "this" is not QTcpSocket right? So, how can that work?
-
@jsulm , this is instance of clsSocketServer which is:
class clsSocketServer : public QTcpServer { Q_OBJECT ...
As I said I tried changing the clsSocketClient to accept QAbstractSocket* but still the same, aren't QTcpServer and QTcpSocket both based on QAbstractSocket ?
-
@SPlatten I'm reffering to this:
clsSocketClient* pClient = new clsSocketClient(this);
What is "this" here? If it is not QTcpSocket then it can't work!
-
@jsulm , I did answer, this is clsSocketServer which is derived from QTcpServer.
-
@jsulm ,@KroMignon , sorted, it's now working and communicating, thank you:
void clsSocketServer::incomingConnection(qintptr sfd) { clsSocketClient* pClient = new clsSocketClient(new QTcpSocket()); pClient->setSocketDescriptor(sfd); addPendingConnection(pClient); }
-
@SPlatten said in QTcpSocket / QTcpServer, connection closed:
class clsSocketClient : public QTcpSocket {
Q_OBJECTpublic: explicit clsSocketClient(QTcpSocket* pClient = nullptr);
...
Please change this to:
class clsSocketClient : public QTcpSocket { Q_OBJECT public: explicit clsSocketClient(QObject *parent = nullptr);
-
This post is deleted! -
@SPlatten said in QTcpSocket / QTcpServer, connection closed:
void clsSocketServer::incomingConnection(qintptr sfd) {
clsSocketClient* pClient = new clsSocketClient(new QTcpSocket());
pClient->setSocketDescriptor(sfd);
addPendingConnection(pClient);
}Why to you do this?
clsSocketClient* pClient = new clsSocketClient(new QTcpSocket());
is an nonsense! -
@SPlatten said in QTcpSocket / QTcpServer, connection closed:
which is derived from QTcpServer
QTcpServer != QTcpSocket
-
@KroMignon It compiles and works, I tried several other things that don't.
-
@SPlatten said in QTcpSocket / QTcpServer, connection closed:
It compiles and works
Doesn't change the fact that it is nonsense.
Do it the way @KroMignon shown you. -
@jsulm , @KroMignon , changed and compiled, still working :)
-
@SPlatten said in QTcpSocket / QTcpServer, connection closed:
changed and compiled, still working :)
It is really disappointing that you don't try to understand what you are doing wrong.
This give the bad taste that you are just placing code together but not have a clue what you are doing.The class constructor
QTcpSocket(QObject *parent)
is used to define the parent object to this instance.
Parent is used, in Qt, to handle automatic instance cleanup when parent instance is destroyed.
This simplify also threading, moving parent instance to a thread will also moves all his "childrens".Please, please, read a little bit of Qt documentation to understand what you are doing.
By doing
clsSocketClient* pClient = new clsSocketClient(new QTcpSocket());
you a creating a class which will have a parent QObject, but for what?And the QTcpSocket instance you have created will never be deleted!!!
This not clean programming!
-
@SPlatten said in QTcpSocket / QTcpServer, connection closed:
the samples FortuneServer and FortuneClient do not use incomingConnection directly either, they are very lean examples. The examples to not call addPendingConnection either.
The important difference here is that the FortuneServer example does not subclass QTcpServer or QTcpSocket. When you subclass it and reimplement functions, there are more gotchas to watch out for.
Your program looks quite complex; I suggest you start by implementing a simple "lean" program from scratch first (without subclassing) and make sure that works. After that, you can gradually add the extra features that you want.