QNetworkAccessManager returning empty results - qt

I am struggling with qnetworkaccessmanager for quite sometime. I googled a lot, but I donot find a solution for this.
I am creating a client using qaccessmanager to talk with a rest server. QNetworkReply is not returning any results. The server is working properly but the client is not returning results. On top of that the server gets called 3 times and sometimes the server is crashing. Hope some one can figure out what is going wrong. I am attaching the client code.
I tried different approches like connecting finished signal of networkaccessmanager, qnetworkreply e.t.c. But all of them ends up in giving the same error "Connection Closed" or the readAll bytearray being empty.
void RestClientCore::ConnectToServer()
{
m_NetworkManager = new QNetworkAccessManager(this);
QUrl url("http://localhost");
url.setPort(5432);
QByteArray postData;
postData.append("/?userid=user");
postData.append("&site=site");
QNetworkReply *reply = m_NetworkManager->post(request,postData);
connect(reply, SIGNAL(readyRead()),this, SLOT(slotReadyRead()));
connect(reply, SIGNAL(finished()), this, SLOT(onRequestCompleted()));
}
void RestClientCore::onRequestCompleted() {
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
if(reply->error())
{
qDebug() <<reply->bytesAvailable() << reply->errorString();
}
else
{
qDebug() << reply->readAll();
}
reply->deleteLater();
}
void RestClientCore::slotReadyRead()
{
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
qDebug() << reply->readAll();
}
Thanks in advance
Regards
Rejo

Related

QNetworkReply::RemoteHostClosedError

I was learning the Github API and wanted to create an Issue on github by Qt.
But, when I submit my Issue, the "Debug Console" said
QNetworkReply::RemoteHostClosedError
(I catched error).
I don't know why, please help me!
Code on Github:
void MainWindow::on_pushButton_2_clicked()
{
QString id = ui->ID_Send->text();
QJsonObject JJ;
QJsonDocument jd;
JJ["title"] = ui->Title->text();
JJ["body"] = ui->Comment->toPlainText();
QHttpMultiPart *part = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart info;
info.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/json"));
jd.setObject(JJ);
info.setBody(jd.toJson());
part->append(info);
QNetworkRequest request;
qDebug()<<"https://api.github.com/repos/MoyuSteve/Comment/issues?client_id="+
client_id+"&client_secret="+client_secret;
request.setUrl(QUrl("https://api.github.com/repos/MoyuSteve/Comment/issues?client_id="+
client_id+"&client_secret="+client_secret));
QNetworkReply* reply = manager->post(request,part);
QObject::connect(reply, &QNetworkReply::finished, [reply, this] () {
if (reply->error() == QNetworkReply::NoError) {
ui->status->setText("ok");
} else {
ui->status->setText("failed");
qDebug()<<reply->error();
}
reply->deleteLater();
});
}
You can take example in this answer or here.
Compared to your code, it sets the header to "application/json".
And it uses a QNetworkAccessManager to send network requests and receive replies.
QUrl url("https://api.github.com/repos/" + owner +"/" + project + "/tags");
qInfo() << url.toString();
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkAccessManager nam;
QNetworkReply * reply = nam.get(request);

Qt5 - Get Content Length while downloading a file from an Url

I am downloading an ".apk" file from a Url with Get method.
The file successfully donwload on my disk from the server.
I actually want to add a progressbar to my program. THE problem is : I can show the bytesReceived but I can't show the totalBytes of the file I am downloading (ContentLenth). How can I get it please from the server.
Here is what i get on my qDebug while downloading:
3498 of -1
799062 of -1
1923737 of -1
3037550 of -1
3200231 of 3200231
Here is my code:
void DownloadApk::LaunchDownload()
{
QNetworkProxy proxy;
proxy.setType(QNetworkProxy::HttpProxy);
proxy.setHostName("proxy");
proxy.setPort(8080);
QNetworkProxy::setApplicationProxy(proxy);
QUrl url("I put my Url here");
QNetworkRequest request(url);
_file = new QFile("C:/Users/Desktop/testdownload/downloadedFile.apk");
_file->open(QIODevice::WriteOnly);
QNetworkAccessManager *_manager= new QNetworkAccessManager;
_reply = _manager->get(request);// Manager is my QNetworkAccessManager
_file->write(_reply->readAll());
connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(error(QNetworkReply::NetworkError)));
connect(_reply, SIGNAL(downloadProgress(qint64, qint64)),
this, SLOT(updateProgress(qint64, qint64)));
connect(_reply, SIGNAL(finished()),
this, SLOT(finished()));
}
void DownloadApk::error(QNetworkReply::NetworkError err)
{qDebug() << err;
// Manage error here.
_reply->deleteLater();
}
void DownloadApk::updateProgress(qint64 read, qint64 total)
{
qDebug() << read <<"of"<<total ;
QByteArray b = _reply->readAll();
QDataStream out(_file);
out << b;
}
void DownloadApk::finished()
{
QMessageBox::information(this, tr("Complete"), tr("Successfully Downloaded"));
// Done
_reply->deleteLater();
_file->close();
// probably delete the file object too
}
I fixed the problem. Actually it was not a QT problem. This Qt code works correctly.
The probleme was from the server that wasn't sending ContentLenth on the header of the reply.

QNetworkAccessManager: how to make sure download is finished?

If I do:
QNetworkRequest newRequest(url);
newRequest.setUrl(url);
QNetworkReply *reply = networkManager->get(newRequest);
connect(reply, SIGNAL(finished()), this, SLOT(onRetrievedDownLoadInfo()));
and
void myClass::onRetrievedDownLoadInfo()
{
QNetworkReply *reply = qobject_cast<QNetworkReply*>(QObject::sender());
if (!reply)
{
ui->upgradeLog->appendPlainText("Download failed, invalid context");
return;
}
//Remeber to delete the reply
//---------------------------
reply->deleteLater();
if (reply->error() != QNetworkReply::NoError)
{
ui->upgradeLog->appendPlainText("Download failed, invalid context");
return;
}
reply->readAll();
...
}
Can I say that when the program reaches line
reply->readAll();
All the content replied by the server is successfully received?
Is it possible the reply->readAll(); only returns part of the reply due to network failure?
The error is here:
connect(reply, SIGNAL(finished()), this, SLOT(onRetrievedDownLoadInfo()));
you are not doing it in the correct way. Use a QNetworkAccessManager to check the network is working:
QNetworkConfigurationManager manager;
req.setConfiguration(manager.defaultConfiguration());
connect(&req, SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)), this, SLOT(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)));

Monitoring internet connection status

How can I monitor internet connection status in qt? What I mean is that I'd like to be able to change icon to active/inactive depend on internet connection being present or not.
If you are using QML, there is NetworkInfo QML element from Qt Mobility package. Also, that contains an example, how to check is WLAN connection present.
I use this code to check the internet status.
bool ConnectivityManager::isOnline()
{
bool retVal = false;
QNetworkAccessManager nam;
QNetworkRequest req(QUrl("http://www.google.com"));
QNetworkReply* reply = nam.get(req);
QEventLoop loop;
QTimer timeoutTimer;
connect(&timeoutTimer, SIGNAL(timeout()), &loop, SLOT(quit()));
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
timeoutTimer.setSingleShot(true);
timeoutTimer.start(3000);
loop.exec();
if (reply->bytesAvailable())
{
retVal = true;
}
return retVal;
}
I've had an issue using a solution similar to the Winston Rodrigues one and Flatpak. This solution was working on almost all computers I have tested but one. Internet connection was not detected for unclear reason (no error was raised). So, here is the solution that works for me in all situations, so far:
bool InternetIsOn()
{
QUrl host("1.1.1.1"); // put here URL (or IP) of your own website if you have one
qDebug() << tr("Checking internet connection: connecting to %1 ...").arg(host.toString());
QTcpSocket* sock = new QTcpSocket(this);
connect(sock, &QTcpSocket::errorOccurred, this, [](QAbstractSocket::SocketError error) {
qDebug() << "This error occured during Internet checking:" << error;
});
sock->connectToHost(host.toString(), 80);
bool connected = sock->waitForConnected(3'000);//ms
if (!connected)
{
sock->abort();
qDebug() << tr("%1 is not reachable. Not connected to the Internet").arg(host.toString());
return false;
}
sock->close();
qDebug() << tr("Connected to the Internet");
return true;
}

QTcpSocket problem

Writing a chat using Qt. Got a problem. My client's QTcpSocket remains in connecting state, but the server emits newConnection() signal. Network session is not required. Why is that? Here is some code:
ChatClient::ChatClient(QObject *parent)
: QObject(parent) {
tcpSocket = new QTcpSocket(this);
QNetworkConfigurationManager manager;
if (QNetworkConfigurationManager::NetworkSessionRequired
& manager.capabilities()) {
qDebug() << "Network session required";
}
connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(error(QAbstractSocket::SocketError)));
connect(tcpSocket, SIGNAL(connected()),
this, SLOT(requestForID()));
connect(tcpSocket, SIGNAL(readyRead()),
this, SLOT(receiveMessage()));
tcpSocket->connectToHost("192.168.0.100", PORT);
}
void ChatClient::requestForID() {
qDebug() << "Connected, requesting for ID";
QByteArray segment;
QDataStream out(&segment, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_7);
out << (quint16)0 << ID;
out.device()->seek(0);
out << (quint16)(segment.size() - sizeof(quint16));
tcpSocket->write(segment);
}
requestForID() is never being executed
ChatServer::ChatServer(QObject *parent)
: QObject(parent) {
tcpServer = new QTcpServer(this);
if (!tcpServer->listen(QHostAddress::Any, PORT)) {
qDebug() << "Unable to start the server"
<< tcpServer->errorString();
}
qDebug() << "Server port" << tcpServer->serverPort();
connect(tcpServer, SIGNAL(newConnection()),
this, SLOT(processConnection()));
}
void ChatServer::processConnection() {
qDebug() << "Incoming connection";
QTcpSocket *clientSocket = tcpServer->nextPendingConnection();
/*connect(clientSocket, SIGNAL(readyRead()),
this, SLOT(readData()));
readData(clientSocket);
connect(clientSocket, SIGNAL(disconnected()),
clientSocket, SLOT(deleteLater()));*/
QByteArray segment;
QDataStream out(&segment, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_7);
out << (quint16)0 << (quint16)Message
<< "Successfully connected";
out.device()->seek(0);
out << (quint16)(segment.size() - sizeof(quint16));
clientSocket->write(segment);
clientSocket->disconnectFromHost();
}
server displays incoming connection and the client does not emit connected remaining in connecting state, doesnt receive server message as well...
Any ideas?
I had the same problem and I found the reason and a solution.
connectToHost may not be called in the contstructor of the main window directly. Why?
The reason is, that the main message loop is not running yet at this time. Internally QAbstractSocketPrivate::fetchConnectionParameters() gets never called and Qt Socket Timeout Timer thinks connection is never established.
The solution is either to call it "delayed" like in
QMetaObject::invokeMethod(this, "OnDelayedConnect", Qt::QueuedConnection);
Or to call waitForConnected() after connectToHost

Resources