QTcpSocket: no readyRead() signal even in Qthread event loop
Hello,
I have to port some app from Qt3 to Qt4 and have problem with slot connected to readyRead signal. It just doesn get called at all. I thought it is because socket wrapper in app gets called from some thread without event loop. I've inherited this wrapper from QThread, moved socket to this thread as described here http://www.qtcentre.org/threads/2716...ain-event-loop, but it still doesn't work. I also tried to instantiate QTcpSocket in run(). Below is stripped version of socket wrapper:
Code:
class ClientSocket
: public QThread{
Q_OBJECT
public:
ClientSocket();
...
public slots:
void test();
private:
};
ClientSocket
::ClientSocket() : QThread(){
m_socket->moveToThread(this);
connect(m_socket, SIGNAL(readyRead()), this, SLOT(test()));
start();
}
bool ClientSocket
::connectToHost(QString host,
int port
) {
if (port == 0) return false;
m_socket->connectToHost(host, port);
return m_socket->waitForConnected(1000);
}
void ClientSocket::write(const char* Data,unsigned int nBytes)
{
{
m_socket->write(Data);
m_socket->flush();
}
}
void ClientSocket::test()
{
stop();
}
void ClientSocket::run()
{
exec();
}
At some place in some thread this class is instantiated in constructor like this:
Code:
SomeClass::SomeClass()
: m_ClientSocket()
{
bool bConnected = m_ClientSocket.connectToHost("localhost", 1000);
if (bConnected)
{
m_ClientSocket.write("rtst", 4);
}
}
I test it with echo server that writes received string back. But test() slot is never called. connect() with Qt::QueuedConnection didn't change anything.
have somebody any idea why it doesn't work?
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
Did you call QThread::start()? Btw why are you using a Socket inside a Thread?
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
start() is called inside constructor (see source code above). Without QThread it doesn't work either. My suggestion was that I didn' get slot called because of missing event loop where ClientSocket gets instantiated. Therefore I started thread with its own event loop and moved socket to this thread. Unfortunately this way it doesn't work as well.
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
Sorry, missed the start() in the contructor.
Why are you thinking, that the event handling is not working? Is the socket not instantiated inside a QApplication? Are you sure, that the socket really receives data? (Did you check it with wireshark or something else)
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
Hi,
I have tried the source with a simple QCoreApplication and get the following message at run-time :
Quote:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x82c7ab8), parent's thread is ClientSocket(0xbfef92fc), current thread is QThread(0x82ba410)
The program is still running but I do not receive any answer too. I think your moveToThread failed, I already got this message when I was using QThread like that.
Are you sure you realy need another event loop? If you are, maybe you should use QThread in a other way, take a look to http://labs.qt.nokia.com/2010/06/17/...oing-it-wrong/.
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
It took some time because Wireshark cannot catch on localhost and I had to setup another PC to test it. But Now I see that response is sent back, so socket should have this data.
@nix: Unfortunately this project is on VS2003 and I don't see qDebug() output and errors like you. I'll try to create socket diret in run(). In this case such error shouldn't occur.
Added after 10 minutes:
Quote:
Originally Posted by
nix
If it would work without QThread event loop, I would be happy, but it doesn't. Threrfore I've tried it with QThread. May be it's also wrong.
I already read this article, but I don't move thread to itself. I move socket to this new thread and this shold be correct. But I'll try it without QThread subclassing. May be it differs...
Added after 6 minutes:
Code:
ClientSocket::ClientSocket()
:m_isRunning(false)
{
connect(m_socket, SIGNAL(readyRead()), this, SLOT(test()));
m_socket->moveToThread(t);
t->start();
This way slot also doesn't get called. And without subclassing QThread I cannot start QThread's event loop because exec() is protected.
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
Hi,
Create the socket into the "start()" method and then call "exec()" to start the event loop of the thread. If you create the QTcpSocket into the "start()" method, this object belongs to the thread that created it, that in this moment is the new thread. Instead if you create the socket into the constructor, the object belongs to the calling thread(main thread in this case).
Quote:
Unfortunately this project is on VS2003 and I don't see qDebug() output and errors like you
I don't remeber which window you have to select, but I think that "results" window shows the console output.
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
Ok but moving the socket was not my point, I try that with your code :
main.c
Code:
#include <QtCore/QCoreApplication>
#include "clientsocket.h"
#include <QThread>
#include <QtDebug>
int main(int argc, char *argv[])
{
ClientSocket m_ClientSocket;
thread->start();
// now we got another thread
m_ClientSocket.moveToThread(thread);
qDebug() << "Main thread is " <<QThread::currentThreadId();
bool bConnected = m_ClientSocket.connectToHost("10.33.17.37", 8000);
qDebug() << "Connexion done";
if (bConnected)
{
qDebug() << "Ask for Id";
m_ClientSocket.write("*rem\n*idn?\n", 10);
}
// For testing don't do a exec() just wait for msec
// Without the processEvent() qDebug not displaying anything but
// the threadid prove the reception is done in the other thread
thread->wait(500); // After 500ms I should have the response or I give up.
a.processEvents();
thread->quit();
thread->wait(100);
return 0;
}
clientsocket.h
Code:
#ifndef CLIENTSOCKET_H
#define CLIENTSOCKET_H
#include <QTcpSocket>
{
Q_OBJECT
public:
ClientSocket();
bool connectToHost
(QString host,
int port
);
void write(const char* Data,unsigned int nBytes);
//void run();
public slots:
void test();
private:
};
#endif // CLIENTSOCKET_H
clientsocket.c
Code:
#include "clientsocket.h"
#include <QDebug>
#include <QThread>
ClientSocket
::ClientSocket() : QObject(){
connect(m_socket, SIGNAL(readyRead()), this, SLOT(test()), Qt::QueuedConnection);
}
bool ClientSocket
::connectToHost(QString host,
int port
) {
if (port == 0) return false;
m_socket->connectToHost(host, port);
return m_socket->waitForConnected(1000);
}
void ClientSocket::write(const char* Data,unsigned int nBytes)
{
{
m_socket->write(Data);
m_socket->flush();
}
}
void ClientSocket::test()
{
qDebug
() <<
"I got something here!!!" <<
QThread::currentThreadId() ;
}
This is the output:
Quote:
Starting /disk2/local/qt/TestDebug/TestDebug...
Main thread is 3070105296
Connexion done
Ask for Id
I got something here!!! 3068005232
/disk2/local/qt/TestDebug/TestDebug exited with code 0
There is something strange with the qDebug in the second thread, it will display nothing until we call a processEvent() but the thread Id displayed in the readyRead connected slot proves that it's the second thread :).
I don't know if you can use it like this in your app but It seems to work fine for me except that I can explain the strange behavior with the qDebug in the second thread.
(You have to take care of the cross thread call in a second time)
Hope it can help
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
Quote:
Originally Posted by
^NyAw^
I don't remeber which window you have to select, but I think that "results" window shows the console output.
Output comes in Output window (below the editor), but it seems for GUI app it doesn't work or shows stdout only, without stderr.
Added after 14 minutes:
@nix: I tried your version, but readyRead still didn't get called in my case. May be it has something to do with fact that it's all is in DLL. But thanks anyway!
Added after 9 minutes:
Quote:
Originally Posted by
^NyAw^
Create the socket into the "start()" method and then call "exec()" to start the event loop of the thread. If you create the QTcpSocket into the "start()" method, this object belongs to the thread that created it, that in this moment is the new thread. Instead if you create the socket into the constructor, the object belongs to the calling thread(main thread in this case).
I tried it, but this way nothing will be sent. Echo server becomes no incoming connection and all hangs after exec() ... I tries exec() in both start() and run(). Will now try without exec() at all.
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
Hi,
Quote:
Output comes in Output window (below the editor), but it seems for GUI app it doesn't work or shows stdout only, without stderr.
I'm not able to tell you wich window is because I have Visual Studio in spanish language. What I'm able to say is that qDebug works perfectly as I can see my qDebug output messages into this window.
Quote:
I tried it, but this way nothing will be sent. Echo server becomes no incoming connection and all hangs after exec() ... I tries exec() in both start() and run(). Will now try without exec() at all.
Are you sure that it hangs on "exec()". Think on that when you call "exec()" the thread enters into an eventLoop. So have your tryied to call "exec()" into the "run()" method after you create the socket?
Code:
void myThread::run()
{
...
//create the socket here
exec(); //The thread enters into the eventLoop, so the next line of code only will be called when you stop the thread.
//delete the socket here, ore close connection, ...
}
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
Quote:
Originally Posted by
^NyAw^
What I'm able to say is that qDebug works perfectly as I can see my qDebug output messages into this window.
You are right. I just tested it with another application and qDebug prints in Output window. May be application I have redirects somewhere standard streams and they go somewhere else.
Quote:
Originally Posted by
^NyAw^
Are you sure that it hangs on "exec()". Think on that when you call "exec()" the thread enters into an eventLoop. So have your tryied to call "exec()" into the "run()" method after you create the socket?
yes, tried it in start() and in run(). Normally run() is executed in new thread and exec() in run() shouldn't affect main thread flow, but in debugger I still hanging in main thread at the line that started the thread...
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
I tested with blocking methods and it works very strange. If I modify write() method so:
Code:
m_socket->write(Data);
m_socket->flush();
m_socket->waitForBytesWritten();
qApp->processEvents();
bool hasData=m_socket->waitForReadyRead();
int num=m_socket->bytesAvailable();
qDebug()<<num<<data;
hasData is true and I can read my data. After that test() slot, connected to readyRead() is called. BUT if I comment
Code:
bool hasData=m_socket->waitForReadyRead();
out then there is no data (num=0) and no test() slot call.
I used TcpSocket and these signals in several projects without any problem, but now I stuck with it and have no idea what could be the problem.
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
Hi,
First of all, are you sure that you need threads for this?
If you comment "waitForReadyRead()" is normal that you get "num == 0" because you are not waiting to get data into the socket, you only ask how many data is into the buffer and the buffer is not filled until some data arrives. You are expecting to have data into the buffer, but the application that have to write data still not wrote it.
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
The client gets response from the server so fast that before the thread starts running.
At the moment when the response arrives, the event loop of the thread has not started yet, so you can not receive the signal.
Try to sleep some time before you start sending message to the server.
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
Quote:
Originally Posted by
^NyAw^
Hi,
First of all, are you sure that you need threads for this?
No, it was just attempt to solve the problem this way.
If you comment "waitForReadyRead()" is normal that you get "num == 0" because you are not waiting to get data into the socket
I did step by step in debugger so that echo server that writes response immediately had enough time to write back. May be the reason was that until I'm in this function there are no events processed and bytesAvailable() relies on it.
Added after 4 minutes:
Quote:
Originally Posted by
hugh_lou
Try to sleep some time before you start sending message to the server.
I did it with sleep and also saw in debugger that thread already started before I send data. It has no effect.
Code:
m_ClientSocket.start();
Sleep(10000);
bool bConnected = m_ClientSocket.connectToHost("localhost", 1000);
if (bConnected) m_ClientSocket.write("rtst", 4);
Added after 10 minutes:
Once again last version of the source code:
Code:
ClientSocket
::ClientSocket() : QThread() {}
bool ClientSocket
::connectToHost(QString host,
int port
) { m_socket->connectToHost(host, port);
return m_socket->waitForConnected(1000);
}
void ClientSocket::write(const char* Data,unsigned int nBytes) {
m_socket->write(Data);
m_socket->flush();
m_socket->waitForBytesWritten();
//qApp->processEvents();
//bool hasData=m_socket->waitForReadyRead();
//int num=m_socket->bytesAvailable();
//QByteArray data=m_socket->readAll();
//qDebug()<<num<<data;
}
}
void ClientSocket::test() {
qDebug
() <<
"I got something here!!!" <<
QThread::currentThreadId() ;
}
void ClientSocket::run() {
bool connected=connect(m_socket, SIGNAL(readyRead()), this, SLOT(test()), Qt::QueuedConnection);
qDebug()<<connected;
//m_socket->moveToThread(this);
exec();
}
Usage:
Code:
SomeClass::SomeClass() : m_ClientSocket() {
m_ClientSocket.start();
Sleep(10000);
bool bConnected = m_ClientSocket.connectToHost("localhost", 1000);
if (bConnected) {
m_ClientSocket.write("rtst", 4);
}
}
@^NyAw^: I also tried the same code without QThread and run(), just QObject as parent. The same strange effect of readyRead() absence.
Added after 15 minutes:
I just tested it inside my echo server app (simple Qt application) an it works! (Talker is the echo server). test() slot gets called. It should has something to do with DLL/EventLoop, I guess...
Code:
int main(int argc, char *argv[])
{
Talker* t=new Talker();
ClientSocket* c=new ClientSocket();
c->start();
Sleep(10000);
bool bConnected = c->connectToHost("localhost", 1000);
if (bConnected)
{
c->write("rtst", 4);
}
return a.exec();
}
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
Hi,
Well, think on that the debugger stops the eventLoop and using sleep also will stop the eventLoop.
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
It's clear, but after sleep it should be possible to send readyRead(). Echo server is another stand alone app and it's event loop not affected by debugger or Sleeps, so it sends data during this sleep.
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
Why are you using a dedicated thread for the socket? You don't need it for anything and it is causing you problems because you are trying to access the socket from within a thread it doesn't belong to.
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
In #3 and #6 I already wrote that I've envolved QThread to get event loop, because it didn't work as I had Client Socket inherited from QObject. This was just suggestion that it doesn't work because of missing event loop. By the way, socket belongs to thread as it's instantiated in run() (see code above). As I wrote before, this all works also if I use this ClientSocket in my simple appplication from main(). But in Dll of project (plugin) I'm now working with, I have a problem that non blocking methods didn't get called whereas blocking methods work.
To avoid further confusions with threads I post version without QThread that behaves the same way.
Code:
class ClientSocket
: public QObject { Q_OBJECT
public:
connect(m_socket, SIGNAL(readyRead()), this, SLOT(test()));
}
virtual ~ClientSocket() {};
bool connectToHost
(QString host,
int port
) { m_socket->connectToHost(host, port);
return m_socket->waitForConnected(1000);
}
void write(const char* Data,unsigned int nBytes) {
{
m_socket->write(Data);
m_socket->flush();
m_socket->waitForBytesWritten();
//bool hasData=m_socket->waitForReadyRead();
//int num=m_socket->bytesAvailable();
//QByteArray data=m_socket->readAll();
//qDebug()<<num<<data;
}
}
public slots:
void test() { qDebug()<<"readyRead()"; }
private:
};
From DLL code it's used like this
Code:
SomeClass::SomeClass() : m_ClientSocket() {
bool bConnected = m_ClientSocket.connectToHost("localhost", 1000);
if (bConnected) m_ClientSocket.write("rtst", 4);
}
test() slot is not called. if I uncomment lines in write() I have expected response (num=4, data="rtst") and slot is called. But waitForReadyRead() shouldn't be called in order to get slot working...
Re: QTcpSocket: no readyRead() signal even in Qthread event loop
Quote:
Originally Posted by
R-Type
In #3 and #6 I already wrote that I've envolved QThread to get event loop, because it didn't work as I had Client Socket inherited from QObject.
The main thread also has (or at least can have) an event loop, I really don't see the point of using a thread here.
Quote:
By the way, socket belongs to thread as it's instantiated in run() (see code above).
Sure, but you are calling the socket's functions directly from the main thread which is forbidden.