PDA

View Full Version : Qnetworkaccessmanager and qnetworkreply are returning an error "connection closed"



gowreesh
28th May 2015, 06:57
Hi,
I am developing a plugin for to transfer a XML file over Http protocol on top of the TCP layer.
I am Able to send the XML body from Client to the Server using Networkaccessmanager and I can able to receive both the header and body at server.
But the issue is am getting an error saying "Connection Closed" from the NetworkReply Even though all my data is transferred to the server.
And also sometimes Server will get called 2 times also for the same Build.
and also sometimes at server side, data will not be received .

Please check my code below.

/* Client_cs.cpp */




Client_CS::Client_CS(QObject* parent): QObject(parent)
{ qDebug() <<"data starting";
client_socket.connectToHost("127.0.0.1", 80);
connect(&client_socket, SIGNAL(connected()), this, SLOT(startTransfer()));
}

Client_CS::~Client_CS()
{}

void Client_CS::startTransfer()
{ QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart filePart;
filePart.setHeader(QNetworkRequest::ContentTypeHea der, QVariant("text/xml"));
filePart.setHeader(QNetworkRequest::ContentDisposi tionHeader, QVariant("form-data; filename=\"text\""));
QFile *file = new QFile(xmllink);
if ( !file->exists() )
{ qDebug() << "File Does not exist";
}
file->open(QIODevice::ReadOnly);
filePart.setBodyDevice(file);
file->setParent(multiPart);
multiPart->append(filePart);
QUrl url("http://127.0.0.1:80");
QNetworkRequest request(url);
pManager = new QNetworkAccessManager();
pReply = pManager->post(request, multiPart);
multiPart->setParent(pReply);
QObject::connect(pReply, SIGNAL(finished()),this, SLOT(replyFinished())); // here is the issue
client_socket.close();
}


void Client_CS::replyFinished()
{ if ( pReply->error() > 0 )
{ qDebug() << "Error occurred: " << pReply->error() << " : " << pReply->errorString();
}
else
{ qDebug() << "Upload success";
}
pReply->deleteLater();
}


/* Server_CS.cpp */



Server_CS::Server_CS(QObject* parent): QObject(parent)
{
qDebug() << "server initiated";
QHostAddress hostadd(QHostAddress::Any);
cs_server.listen(hostadd, 80);
connect(&cs_server, SIGNAL(newConnection()),this, SLOT(acceptConnection()));
}

Server_CS::~Server_CS()
{
cs_server.close();
}

void Server_CS::acceptConnection()
{
_cs_Socket = new QTcpSocket(this);
qDebug() << "server got new connection";
_cs_Socket = cs_server.nextPendingConnection();
connect(_cs_Socket, SIGNAL(readyRead()),this, SLOT(startRead()));
}

void Server_CS::startRead()
{
qDebug() << "server started reading the data received";
QByteArray buffer;
buffer = _cs_Socket->read(_cs_Socket->bytesAvailable());
qDebug() <<"value read from the port is :"<< buffer ;
// _handleIncomingData(buffer);
_cs_Socket->close();

}



/* main.cpp */



int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

Server_CS server;

Client_CS client;

return a.exec();
}



The error output am getting is
Error occured: 2 : "Connection closed"


Please give me some suggestion to resolve this issue.

Thank you

seneca
28th May 2015, 07:11
You immediately close the socket without giving the eventloop time to process the connections (which will havppen in a.exec()).
Move the socket close to the destructor.

wysota
28th May 2015, 07:18
What is client_socket? How is it related to the functionality of the provided snippet? Do you use the socket in any way?

gowreesh
28th May 2015, 07:54
What is client_socket? How is it related to the functionality of the provided snippet? Do you use the socket in any way?

Actually my requirement is to develop a plug-in using Http protocol over TCP layer.
That's the reason first am trying to establish a TCP connection with server and client by using


client_socket.connectToHost("127.0.0.1", 80); //at the constructor of client
connect(&client_socket, SIGNAL(connected()), this, SLOT(startTransfer()));

Above code is at the Client side. and below code at the server side


cs_server.listen(hostadd, 80); //at the constructor of server
connect(&cs_server, SIGNAL(newConnection()),this, SLOT(acceptConnection()));

And even without using "client_socket" I can establish a connection directly by calling the function like below

client.startTransfer(); // in the main function
But for to make a proper TCP connection(to receive signal connected ), I have developed like this.

anda_skoa
28th May 2015, 08:14
Actually my requirement is to develop a plug-in using Http protocol over TCP layer.

That doesn't answer wysota's question.
What do you need the client_socket for, i.e. why do you establish two connections from the client to the server.

Also you are creating a QTcpSocket in Server_CS::acceptConnection() and then immediately forgetting about it (leaking it).

Since your server can only work with one connection at a time (using a single socket member variable _cs_Socket) you should first get rid of the second connection you are currently establishing and then test again.

Your server and client code are currently "out of sync"

Cheers,
_

gowreesh
29th May 2015, 03:56
:eek: Sorry , I have understood the concept wrongly.
Please check my modified code below .
After the code updation, am facing an issue with signal "SIGNAL(finished())". This signal is not getting emitted . And that's the reason the function replyFinished() is not getting called.
I tried understanding this problem using Debugger also . But it is giving an time-out error(saying that gdb could have stuck in endless loop). Please find the attachment of Debugger output error .


/* Client_CS.h */
class Client_CS: public QObject
{
Q_OBJECT
public:
QNetworkReply *pReply;
QNetworkAccessManager *pManager;
Client_CS(QObject* parent = 0);
~Client_CS();
void startTransfer();
public slots:
void replyFinished();

};

/* Client_CS.cpp */

Client_CS::Client_CS(QObject* parent): QObject(parent)
{ qDebug() <<"data starting";
}

Client_CS::~Client_CS()
{
}

void Client_CS::startTransfer()
{
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart filePart;
filePart.setHeader(QNetworkRequest::ContentTypeHea der, QVariant("text/xml"));
filePart.setHeader(QNetworkRequest::ContentDisposi tionHeader, QVariant("form-data; filename=\"text\""));
QFile *file = new QFile(xmllink);
if ( !file->exists() )
{ qDebug() << "File Does not exist";
}
file->open(QIODevice::ReadOnly);
filePart.setBodyDevice(file);
file->setParent(multiPart);
multiPart->append(filePart);
QUrl url("http://127.0.0.1:80");
QNetworkRequest request(url);
pManager = new QNetworkAccessManager();
pReply = pManager->post(request, multiPart);
multiPart->setParent(pReply);
QObject::connect(pReply, SIGNAL(finished()),this, SLOT(replyFinished()));
}

void Client_CS::replyFinished()
{
qDebug()<<"got the reply from the network";
if ( pReply->error() > 0 )
{ qDebug() << "Error occurred: " << pReply->error() << " : " << pReply->errorString();
}
else
{ qDebug() << "Upload success";
}
pReply->deleteLater();
}





/* Server_CS.h */

class Server_CS: public QObject
{
Q_OBJECT
public:
Server_CS(QObject * parent = 0);
~Server_CS();
public slots:
void acceptConnection();
void startRead();
private:
QTcpSocket* _cs_Socket;
QTcpServer cs_server;
};

/* Server_CS.cpp */

Server_CS::Server_CS(QObject* parent): QObject(parent)
{ qDebug() << "server initiated";
QHostAddress hostadd(QHostAddress::Any);
cs_server.listen(hostadd, 80);
connect(&cs_server, SIGNAL(newConnection()),this, SLOT(acceptConnection()));
}

Server_CS::~Server_CS()
{cs_server.close();
}

void Server_CS::acceptConnection()
{ qDebug() << "server got new connection";
_cs_Socket = cs_server.nextPendingConnection();
connect(_cs_Socket, SIGNAL(readyRead()),this, SLOT(startRead()));
}

void Server_CS::startRead()
{ qDebug() << "server started reading the data received";
int size;
size = _cs_Socket->bytesAvailable();
QByteArray data;
data.resize(size);
_cs_Socket->read(data.data(), size);
qDebug() <<"value read from the port is :"<< data ;
// _handleIncomingData(buffer);
}




/* MAIN.cpp */

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Server_CS server;
Client_CS client;
client.startTransfer();
return a.exec();
}


11183

wysota
29th May 2015, 07:09
Does the server produce any output for the client? Does it respect the HTTP protocol when (if) doing so?

gowreesh
29th May 2015, 08:54
Does the server produce any output for the client? Does it respect the HTTP protocol when (if) doing so?

Actually I don't need a response from the server, and even the data which I am passing at the client is receiving properly at the server side.
But as per the QNetworkAccessManager I should get a reply from the server, so only I am trying to validate the network reply.

Actually as per my project requirement, the XML data which is received at the server side will goes further to the decoder for further processing.
and then the Encoder at the server side will send the updated XML data to the client using a separate port. (well I need to implement this part still. and my plan is to reuse the code which I have for client to server.)

Please correct me if I am wrong.
Thank you

wysota
29th May 2015, 09:00
Actually I don't need a response from the server, and even the data which I am passing at the client is receiving properly at the server side.
But as per the QNetworkAccessManager I should get a reply from the server, so only I am trying to validate the network reply.
If you are not sending a reply then why do you expect that the client receives it? How can the client know that the request is finished?

You are using HTTP protocol as the transport layer but it seems to me this was not your conscious decision, right?

gowreesh
31st May 2015, 12:44
If you are not sending a reply then why do you expect that the client receives it? How can the client know that the request is finished?

You are using HTTP protocol as the transport layer but it seems to me this was not your conscious decision, right?

I have understood that when the "cs_server.close()" is called , the server connection will end and so client will also come to know.
If am wrong, please tell me How to inform back the client ???
and my requirement is to develop a Http connection over a tcp layer, please tell me if am doing wrong.

Sorry for asking many questions . I am a fresher . new to c++ and QT . Everything am newly learning and implementing.

anda_skoa
31st May 2015, 12:58
I have understood that when the "cs_server.close()" is called , the server connection will end and so client will also come to know.

This closes the listening server socket, not the connection socket (in you code that would be "_cs_Socket")



If am wrong, please tell me How to inform back the client ???

A HTTP server would at least respond with an HTTP response code.



and my requirement is to develop a Http connection over a tcp layer, please tell me if am doing wrong.

Client side this is taken care of by QNetworkAccessManager.

Maybe you could clarify what you are actually trying to develop?
A client using HTTP to upload data to a webserver?
A webserver to receive uploads from a webclient?
Both?

Cheers,
_

gowreesh
1st June 2015, 01:26
Client side this is taken care of by QNetworkAccessManager.

Maybe you could clarify what you are actually trying to develop?
A client using HTTP to upload data to a webserver?
A webserver to receive uploads from a webclient?
Both?

Cheers,
_

Thanks for the response.
My plan of developing is as per below..
I have 2 isolated system's that is system1 and system2.
where as the system1 gives the output data as a XML file.
where the system2 is a simulator which accepts input as XML file data , and then it further process the received XML file data and returns an updated XML file data.

I have assumed that System1 is a Client and system2 is a Server.
My intention is to develop an interface between these 2 system's.

Initially "my interface for client"(Client_CS.cpp) receives the XML file from the system1 . and the received XML file data will be sent to my interface for server(Server_CS.cpp) through the http protocol.
And this received XML data at Server_CS.cpp will be further sent to the decoder.The decoder will pass this data to the system2.
and this part only am trying to implemented above. and this one is done using port 80.
(Note : I am no need to worry about the Decoder and Encoder part , that part is already there and its not in my scope to develop. and I just need to call the Decoder and Encoder in my interface)

where there is a one more requirement, I still need to develop i.e
the system2 will give the updated XML data to the encoder. and My "interface at server" will read this encoder data and send it to the client interface using http protocol with different port 8080. and the received data at "client interface" will be sending to the system1. and am planning to reuse the same above code for this requirement with different port number.


My issue is , am just expecting any reply from the QNetworkAccessManager because the signal finished is not getting emitted only. Even though this finished signal is not getting emitted But still am able to receive the full data at the server side.
Can I ignore this reply ? or its mandatory to get a reply from the QNetworkAccessManager, If so then please tell how to get this signal emitted.
and please tell me if you find any incoherence with my above code and requirement.

wysota
1st June 2015, 06:24
Why have you chosen HTTP as the transport protocol?

gowreesh
1st June 2015, 07:04
Why have you chosen HTTP as the transport protocol?


my project manager wants me to develop this plugin only by using Http protocol.
Sorry I don't know why Http protocol only.

wysota
1st June 2015, 09:15
my project manager wants me to develop this plugin only by using Http protocol.

Are you going to implement an HTTP server as well? From your previous responses it seems that you are but the same responses seem to suggest you do not understand that protocol at all. Are you 100% sure what you are doing?