QTcpSocket calling readyRead multiple times
-
I'm messing around with
QTcpSocket
in order to understand how it works. I'm trying to download a 1MB file from the internet and it's callingreadyRead
multiple times.How does QTcpSocket works? And why is it calling
readyRead
multiple times?#include <QCoreApplication> #include <QUrl> #include <QDebug> #include <QObject> #include <QTcpSocket> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); auto socket = new QTcpSocket; QUrl url = "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"; QObject::connect(socket, &QTcpSocket::connected , [=] () { qDebug() << "connected"; QString target = url.path(); if (! url.query().isEmpty()) { target.append(QString("?%1").arg(url.query())); } QStringList headerList; headerList << QString("GET %1 HTTP/1.1").arg(target); headerList << QString("Host: %1").arg(url.host()); headerList << "\r\n"; auto headers = headerList.join("\r\n"); socket->write(headers.toStdString().c_str()); }); QObject::connect(socket, &QTcpSocket::disconnected , [=] () { qDebug() << "disconnected"; }); QObject::connect(socket, &QTcpSocket::readyRead , [=] () { qDebug() << "reading..."; }); socket->connectToHost(url.host(), url.port(80)); if (! socket->waitForConnected()) { qDebug() << "Error: " << socket->errorString(); } return a.exec(); }
-
@Natoleet
Hi and welcome to devnetEvery time the TCP socket receives information the readyRead signal is issued. Typically it depends on size of information and certainly also on computer and internet speed. Only for very tiny message you may rely upon that the signal may be triggered only once.
Personally I think the fortune client and fortune server examples are a good entry for understanding the way of implementation. You can run both in parallel on the same machine. When you have one of them in the debugger it is also easy to play around towars what you try to achieve.
-
Basically you can what ever you receive handle as usual in C++. E.g. you can read the socket byte by byte and store in a std::fstream or you can use also QDataStream stuff.
However, in your case QNetworkAccessManager might be a better choice. It would download the file at once.
-
@Natoleet using
QNetworkAccessManager
you can connect theQNetworkAccessManager::finished(QNetworkReply*)
orQNetworkReply::finished()
signal to a slot that uses QNetWorkReply::readAll()' signal:void MyClass::onRequestComplete(QNetworkReply * reply) { if (!reply.error ()) { QFile result {"my_result.txt"}; result.write (reply->readAll ()); } reply->deleteLater (); }
-
@bsomervi I'm not interested in
QNetworkAccessManager
I want to understand the sockets and use it with HTTP.
I tried to read but the first time thatreadyRead
is called is with the headers and the other times is with the body.
I want to get the header separated and save the body in a file. -
There will not be a rule when readyRead is called. It completely depends on the factors as described above. You like to separate responses you need other means in order to do so.
Certainly you can use QTcpSocket also for file download with http. However, the idea of Qt is to make live a bit easier. QNetworkAccessManager has been introduced to allow file download with minimal coding. In that case you would also get a readyRead signal, but only once at the end.
In your approach you basically have to replicate some of this functionality. For small files you may receive only one readyRead signal at the end. However, for larger files you will receive several readyRead. You have to collect the chunks and assemble the complete file and furthermore check somehow if it is completed.As already posted above
@koahnig said:Basically you can what ever you receive handle as usual in C++. E.g. you can read the socket byte by byte and store in a std::fstream or you can use also QDataStream stuff.