Solved QTcpServer readyRead() Signal emited twice
-
I have QTcpServer. I want to send large data from client side and how to catch signal, when all data is received on server?
"while (socket->bytesavailable)" doesn't work.For example:
when qbytearray size is 9000, which is send from client, on the server it's 4000 or 5000...
Example Two:
In this Case readyRead() SIGNAL Is Emited 8 times.
void Client::SendMessage(std::vector<QString>) { MyClass _Send; _Send.Age = 22; _Send.School = 14; _Send.Name = "Taz"; QVector<MyClass2> vv; for (int i = 0; i < 15000; i++) { vv.push_back(MyClass2(24, "leri")); vv.push_back(MyClass2(22, "tazo")); } _Send.vctr = vv; QByteArray bytes; QDataStream stream(&bytes, QIODevice::WriteOnly); int FunctionUID = 331; int ij, ik = ij = 169; MyClass2 faf(-31, "15"); stream << FunctionUID << _Send << faf << ij << ik; socket->write(bytes); } void Server::ImReady() { QByteArray buf; buf = socket->readAll(); QDataStream stream(&buf, QIODevice::ReadOnly); int FunctionUID, ij, ik; MyClass vv; MyClass2 vv1; stream >> FunctionUID >> vv >> vv1 >> ij >> ik; qDebug() << vv.vctr.size() << "faf"; } void Server::incomingConnection(qintptr val) { qDebug() << "Client Connected" << val; socket = new QTcpSocket; socket->setSocketDescriptor(val); if (!socket) { return; } connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater())); connect(socket, SIGNAL(readyRead()), this, SLOT(ImReady())); }
-
QTcpServer has no readyRead signal
You are probably referring to the readyRead signal emitted by QTcpSocket
The readyRead is emitted when data is available. Since the socket cannot know when the transmission is finished, it cannot wait until the end of the transmission. Therefore, especially with large amount data received, the signal is triggered, but it is also likely that not all data may caught with a "while (socket->bytesavailable)" and the slot will be finished. However when exitting the slot routine, the event loop shall trigger again the signal.
For large data amounts this is not a surprise. It all depends on a number of factors such as internet speed and speed of your computer.
-
@koahnig
I have the same problem.. so what is solution? -
@L.Gogs said in QTcpServer readyRead() Signal emited twice:
I have the same problem..
It is not a problem!
-
@L.Gogs You need some protocol to know when all data was transferred. For example you can first send the size (number of bytes) of the data you're going to send. Then you send the data. The receiver first reads the size and then reads as long as it received as many bytes as the size was.
-
@jsulm said in QTcpServer readyRead() Signal emited twice:
@L.Gogs You need some protocol to know when all data was transferred. For example you can first send the size (number of bytes) of the data you're going to send. Then you send the data. The receiver first reads the size and then reads as long as it received as many bytes as the size was.
To add to this, you may need some sort of a buffer in case you are sending large amounts. It all depends on your goals.
-
@koahnig
I'm using QByteArray -
You can use anything you like for buffering. It is merely a decision for what and how you like to use it later on. Buffering is more a term for being aware that you may have to keep a copy of what you have received so far.
-
@koahnig
Ok. Thanks :) -
Hi
just as note to this.
The classic error is to do
void DataReadSignal()
{
QByteArray buf;
buf = socket->readAll(); // it might not read all in one go.
}
where it should have been
buf += socket->readAll();
if (buf.size() >= expected_size) ProcessData();and QByteArray buf; should be a member of the class, not local variable.
-
Thank you all.
void Client::SendMessage(std::vector<QString>) { MyClass _Send; _Send.Age = 22; _Send.School = 14; _Send.Name = "Taz"; QVector<MyClass2> vv; for (int i = 0; i < 15000; i++) { vv.push_back(MyClass2(24, "leri")); vv.push_back(MyClass2(22, "tazo")); } _Send.vctr = vv; QByteArray bytes; QDataStream stream(&bytes, QIODevice::WriteOnly); int FunctionUID = 3311; int ij, ik = ij = 169; MyClass2 faf(-31, "15"); stream << FunctionUID << _Send << faf << ij << ik; QString sz = QString::number(bytes.size() + 10); while (sz.size() != 10) { sz += " "; } bytes.insert(0, sz); qDebug() << bytes.size() << "ss"; socket->write(bytes); socket->flush(); } void Server::ImReady() { QString foo = ""; buf += socket->readAll(); for (int i = 0; i < 10; i++) { foo += buf[i]; } if (buf.size() < foo.toInt()) { qDebug() << "jer adrea" << buf.size() << foo.toInt(); return; } qDebug() << "mzadaa" << buf.size(); QDataStream stream(&buf, QIODevice::ReadOnly); // int l, ij, ik; // MyClass vv; // MyClass2 vv1; // stream >> l >> vv >> vv1 >> ij >> ik; // qDebug() << vv.vctr.size() << l; }
-
Hi
To be on the sure side, i would dofor (int i = 0; i < 10; i++) {
foo += buf[i];
}
-->
if( buf.size() > 10 )
for (int i = 0; i < 10; i++) {
foo += buf[i];
}else you would go out of range with buf[i]; in case a small data set was sent.