Reading Data from QNetworkReply Returns Nothing
-
Hi All,
I am trying to read and write data using QNetworkReply the peice of code able to send data and could write data to server but I am not able to fetch data from server to local running client;
Client side code as follows:
void PostDataRequest(QString RegName,QString RegAdd,QString EnterData) { const char* USERAGENT = "Mozilla/Firefox 3.6.12"; QString m_url = "http://" + m_ServerIP + ":" + m_Port; QUrl myURL(m_url); QNetworkRequest request(myURL); request.setRawHeader("User-Agent", USERAGENT); request.setRawHeader("Content-Type", "application/json"); QNetworkAccessManager mgr; QUrlQuery qu; qu.addQueryItem("RegName", RegName); qu.addQueryItem("RegAdd", RegAdd); qu.addQueryItem("EnterData", EnterData); qu.addQueryItem("Value", "@@@"); QUrl params; params.setQuery(qu); QNetworkReply *reply = mgr.post(request, params.toEncoded()); QEventLoop eventLoop; QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit())); eventLoop.exec(); QString str_Recdata = reply->readAll(); qDebug() << "Success Receive data: " << str_Recdata; return str_Recdata; }
Above code is sending data using post but I am not able to get reply from server.
Where server Code is :
void readyRead() { QTcpSocket *socket = static_cast<QTcpSocket*>(sender()); int BytesAvl(socket->bytesAvailable()); QByteArray bufferData = QByteArray::fromRawData(socket->readAll(),BytesAvl); json::mycounter = bufferData.indexOf(json::srch,0); bufferData = bufferData.mid(json::mycounter); if(!(bufferData.size() < sizeof(int))){ if(socket->state() == QAbstractSocket::ConnectedState) { socket->write(bufferData,1); //write size of data // socket->write(bufferData); //write the data itself qDebug() <<"Waiting for Byters " << socket->waitForBytesWritten(); socket->close(); if(socket->state() == QAbstractSocket::ConnectedState) qDebug() << "\ntrue"; else qDebug() << "\nFalse"; } // int BytesSend(socket->write((const char *)bufferData,bufferData.size())); // qDebug() << "BytesSend"<< BytesSend;// << "Connection "<<connected; emit dataReceived(bufferData); } bufferData.clear(); }
Where QDebug Output is :
Waiting for Byters true
False
DATA "RegName=NA&RegAdd=NA&EnterData=Status&Value=@@@" //Output of Emit Signal
Success Receive data: "" // NO_DATA_HEREWhere Byte received is Zero I am stucked help me through this!!!!
Thanks for Time!!!
Praveen
-
@praveen0991kr
check if the reply has an error before reading from it.Also i noticed that you close the socket in the server?
Then you check if the connection state is still connected?
And you do all this on the readyRead slot, which just tells you that there data to read, but it still may be that there is more data on the socket incoming later on.But as i said you are closing the connection on the first data that comes in.
Also you should call flush() after you are done writing data on the socket, to make sure everything is sent.
Better useQTcpSocket::disconnectFromHost()
which does it implicitly.But anyway:
Since you are using QNetworkAccessManager::post() you receive a HTTP request on the server.
So you need to implement HTTP parsing in your server. Which means parse all the HEADERS and read the Content-Length. After the header section is fully received you need to read the amount of bytes from the Content-Length header.
Only then you are finished with reading, can write your reply and can close the connection.I am not sure if that's what you want ;)
Maybe it's better to use QTcpSocket directly rather than QNetworkAccessManager to send the data to the server. Then you can think of your custom format of messages.
E.g. "<DataSize>|<EncodedData>"
On the server you reading until you find your delimiter (|
in this example). And keep reading until you have read <DataSize> bytes from the socket. -
Thanks for Reply !!!
I am able to read data in myReadyRead() and after parsing I got the Data that I have sent from void PostDataRequest(QString RegName,QString RegAdd,QString EnterData) i.e : 47 Bytes as I have mention in code:
after checking bufferData(QByteArray) I am writing back to same socket but no luck !!!!!
and disconnecting from host as per your suggestion . Emitting data through required result for that I am sure bufferData that is created is correct.Could you pls. ensure the writing steps in socket is correct i.e socket->write() and close steps
void JsonServer::myreadyRead() { QTcpSocket *socket = static_cast<QTcpSocket*>(sender()); int BytesAvl(socket->bytesAvailable()); QByteArray bufferData = QByteArray::fromRawData(socket->readAll(),BytesAvl); json::mycounter = bufferData.indexOf(json::srch,0); //QByteArray srch("Re"); bufferData = bufferData.mid(json::mycounter); if(!(bufferData.size() < sizeof(int))){ if(socket->state() == QAbstractSocket::ConnectedState) { int BytesWritten = socket->write(bufferData,bufferData.size()); //write size of data qDebug() << BytesWritten; //47 Bytes are Written socket->disconnectFromHost(); emit dataReceived(bufferData); //BufferData Contain "RegName=NA&RegAdd=NA&EnterData=Status&Value=@@@" after HTTP header return; } } bufferData.clear(); }
QDebug Output :
47
DATA: "RegName=NA&RegAdd=NA&EnterData=Status&Value=@@@"
Success Receive data: ""Thanks
Praveen -
@praveen0991kr
did you check if a error is returned in the network reply (on the client side)? -
After adding this code I got :
QNetworkReply *reply = mgr.post(request, params.toEncoded());
QString str_Recdata = reply->errorString(); qDebug() <<"Error String : "<< str_Recdata; QEventLoop eventLoop; QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit())); eventLoop.exec(); qDebug() << "Success Receive data: " << str_Recdata;
Success Receive data: "Unknown error"
-
@praveen0991kr
of course you should read the error after the reply has finished, not before... -
I have added some Code : sourcefile.cpp
QString CRWWebCall::PostDataRequest(QString RegName,QString RegAdd,QString EnterData) { const char* USERAGENT = "Mozilla/Firefox 3.6.12"; QString m_url = "http://" + m_ServerIP + ":" + m_Port; qDebug() << m_url; //QUrl myURL(QString("http://localhost:8003")); QUrl myURL(m_url); QNetworkRequest request(myURL); request.setRawHeader("User-Agent", USERAGENT); request.setRawHeader("Content-Type", "application/json"); QNetworkAccessManager mgr; QUrlQuery qu; qu.addQueryItem("RegName", RegName); qu.addQueryItem("RegAdd", RegAdd); qu.addQueryItem("EnterData", EnterData); qu.addQueryItem("Value", "@@@"); QUrl params; QNetworkReply *reply; params.setQuery(qu); connect(&mgr, SIGNAL(finished(QNetworkReply *)), this, SLOT(finished(QNetworkReply *))); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError))); reply = mgr.post(request, params.toEncoded()); QString str_Recdata = reply->errorString(); //qDebug() <<"Error String : "<< str_Recdata; QEventLoop eventLoop; QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit())); eventLoop.exec(); qDebug() << "Success Receive data: " << str_Recdata; return str_Recdata; }
Some Code In header File:
private slots: void finished(QNetworkReply * reply ) { qDebug() << "Bytes"<< reply->bytesAvailable(); if(reply->error() !=QNetworkReply::NoError) { QMessageBox::warning(0, QString("NetworkAccessManager NetworkReply"), QString("QNetworkReply error string: \n") + reply->errorString(), QMessageBox::Ok); } } void onError(QNetworkReply::NetworkError err ) { if(err !=QNetworkReply::NoError) { QMessageBox::warning(0, QString("Error!"), QString("Error loading webpage: \n") + QString::number(err), QMessageBox::Ok); } }
Thanks for Reply !!
-
@praveen0991kr
damn...thats the drawback of using QNetworkAccessManager with a plain tcp socket.Your response also has to be a HTTP response in order to make QNetworkReply work properly.
E.g.
HTTP/1.0 200 OK Date: Fri, 01 Jan 1970 23:59:59 GMT Content-Type: text/html Content-Length: 1259 <CONTENT-with-a-size-of-1259-bytes>
So the most important is the first line that says everything was ok. Which is reflected by QNetworkReply's error.
I would take this as an minimal example for an response, don't know for sure which headers are mandatory.
Note the empty line between the header and body section! And each line should end with\r\n
See RFC-2616 for more details. -
I had the same issue. The QIODevice::readAll() (which is called from QNetworkReply) function states this issue:
This function has no way of reporting errors; returning an empty QByteArray can mean either that no data was currently available for reading, or that an error occurred. This function also has no way of indicating that more data may have been available and couldn't be read.
The resolution is to connect QIODevice::readyRead to as per the documentation:
connect(reply, &QIODevice::readyRead, this, [=]() { QByteArray response = reply->readAll(); qDebug() << response; });