PDA

View Full Version : Challenging QTcpSocket reliability problem



Raccoon29
13th January 2009, 09:13
Hi everyone,

I have found a strange behavior by QTcpSocket working on it.
The explanation isn't easy, but I'll try it anyway.

The idea was to create a thread in the application that works with a QTcpSocket to, of course, connect to a server.

So, subclass QThread, and there what is needed for the socket.

Now, depending on how and where QTcpSocket is declared, connection is successful or not.
Details:
considering the same code to connect, that is a simple

socket->connectToHost("someserver",someport);
let's change the QTcpSocket declaration.

1) as a local variabile in run() (QThread::run() reimplementation)

QTcpSocket socket;
socket.connectToHost("server...",port);
and in this way works fine.

2) as a dinamically a allocated pointer in thread class (member pointer)

class mysocketthread:public QThread
{
private:
QTcpSocket *socket;
...
};

mysocketthread::mysocketthread()
{
socket=new QTcpSocket();
...
}

void mysocketthread::run()
{
socket->connectToHost("server...",port);
...
}
and in this way keeps failing the connection, giving a constant "Connection refused".

Maybe I'm missing something, but I think of this as quite strange... isn't it?

jpn
13th January 2009, 09:19
Maybe I'm missing something, but I think of this as quite strange... isn't it?
It's not that strange but a clear misuse of QTcpSocket. QTcpSocket is not thread safe.

When you instantiate "mysocketthread" in the main thread, the constructor of "mysocketthread" gets executed immediately in the main thread. Later on when you call QThread::start(), the run() method will get executed in the newly started thread context. This means that "mysocketthread::mysocketthread()" and "mysocketthread::run()" are executed in different threads. Be careful with such code.

Anyway, what do you need a thread for in the first place? QTcpSocket works asynchronously.

seim
13th January 2009, 10:09
If you need it (for example for a driven long data transfers or just because more threads in one application need to communicate via one connection with other application - it is similar by some database interfaces, for hiding concrete behaviour, etc.), you can use the common pattern of private object created in run() method of a QThread descendant. The QThread descendant serves as a wrapper, that envelops direct calls from other threads and redirects them asynchronnously to private object with using signal-slot mechanism. The private object manages all the stuff around the tcp or database connection.. Locking access to this private object is another story.. and depends on livecycle and use of your wrapper/private object.

Raccoon29
13th January 2009, 10:38
It's not that strange but a clear misuse of QTcpSocket. QTcpSocket is not thread safe.

When you instantiate "mysocketthread" in the main thread, the constructor of "mysocketthread" gets executed immediately in the main thread. Later on when you call QThread::start(), the run() method will get executed in the newly started thread context. This means that "mysocketthread::mysocketthread()" and "mysocketthread::run()" are executed in different threads. Be careful with such code.


Oh I see, so now I really understand the meaning of that "thread safe" attribute :)
Eventually I was missing something :P
Thanks,thanks,thanks!
By the way, I used thread for a sort of experiment...

@seim thank you for the suggestion, but I think I'll wipe out threads nearing some sockets ;)