PDA

View Full Version : My server (using QTcpServer and QTcpSocket) crashes



supergillis
2nd June 2010, 14:05
This is the first server application I make using Qt. I've checked the examples in the documentation, but I couldn't find what was wrong...

The code

This is my server (subclass of QTcpServer) code:

void Server::start(QHostAddress address, unsigned int port)
{
listen(address, port);
}

void Server::stop()
{
close();
}

void Server::incomingConnection(int descriptor)
{
try
{
// The session is a QThread.
// When the thread finishes, the object executes deleteLater().
// So I think we don't need to worry about a memory leak.
Session* session = new Session(descriptor, this);
session->start();
}
catch(Exception& exception)
{
qDebug() << "Error:" << exception.message();
}
}
And this is the code of the session (subclass of QThread with socket a QTcpSocket):

Session::Session(int descriptor, QObject* parent): QThread(parent)
{
if(!socket.setSocketDescriptor(descriptor))
throw Exception("Unable to set session descriptor!");
QObject::connect(this, SIGNAL(finished()), this, SLOT(deleteLater()));
qDebug() << "[Session] constructed";
}

Session::~Session()
{
// If the socket is still open, then we need to close it.
if(socket.isOpen())
socket.close();
qDebug() << "[Session] destructed";
}

void Session::run()
{
while(socket.isOpen() && socket.waitForReadyRead())
available();
qDebug() << "[Session] leaving main loop";
}

void Session::available()
{
// Read the data.
QByteArray data = socket.readAll();
qDebug() << "read" << data.size() << "bytes";
}

The problem

Now when I connect and send data to the server, it receives it.
So the server gives this output:

[Session] constructed
read 151 bytes
The server doesn't answer yet, so I just close the client connection, and BANG!

The program has unexpectedly finished.
/mnt/Server/Projects/qtibia/qtibia exited with code 0

So something happens when I close the connection that makes the server crash. I've tried to leave out the delateLater() slot, and all kind of stuff... Sometimes it just works, and sometimes it just crashes...

What am I doing wrong?

wysota
2nd June 2010, 14:19
One of the problem surely is that you create the socket in the main thread and try to access it in the session thread. Remember the constructor of your Session object runs in the main thread and not in the session thread. You don't need any theads there, by the way - especially that you are waiting for incoming data all the time there so you can just connect the readyRead() signal to a slot and have a single thread for everything.

supergillis
2nd June 2010, 14:40
Ok! Thanks for the fast reply!
I think I understand what you mean, actually I'm pretty sure, because I changed it and it works now :).


This is what I got now:

Session::Session(int descriptor, QObject* parent): QTcpSocket(parent)
{
if(!setSocketDescriptor(descriptor))
throw Exception("Unable to set session descriptor!");
QObject::connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater()));
QObject::connect(this, SIGNAL(readyRead()), this, SLOT(available()));
qDebug() << "[Session] constructed";
}

Session::~Session()
{
// If the socket is still open, then we need to close it.
if(isOpen())
close();
qDebug() << "[Session] destructed";
}

void Session::available()
{
// Read the data.
QByteArray data = readAll();
qDebug() << "read" << data.size() << "bytes";
}

void Server::incomingConnection(int descriptor)
{
try
{
// The session is a QTcpSocket.
// When the client disconnects, the object executes deleteLater().
// So I think we don't need to worry about a memory leak.
new Session(descriptor, this);
}
catch(Exception& exception)
{
qDebug() << "Error:" << exception.message();
}
}

Also, is this necessary, or does deleting the socket automatically close it too?

// If the socket is still open, then we need to close it.
if(isOpen())
close();

wysota
2nd June 2010, 15:32
Deleting a socket should close it but not gracefully (you should wait for the other end to close the connection too). But if you are sure you are not the one initiating the closing, it's fine.