Results 1 to 20 of 26

Thread: QTcpSocket: no readyRead() signal even in Qthread event loop

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Sep 2010
    Posts
    22
    Thanks
    4
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows Maemo/MeeGo

    Default 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:
    Qt Code:
    1. class ClientSocket : public QThread
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6. ClientSocket();
    7. ...
    8. public slots:
    9. void test();
    10.  
    11. private:
    12. QTcpSocket* m_socket;
    13. };
    14.  
    15. ClientSocket::ClientSocket() : QThread()
    16. ,m_socket(new QTcpSocket())
    17. {
    18. m_socket->moveToThread(this);
    19. connect(m_socket, SIGNAL(readyRead()), this, SLOT(test()));
    20. start();
    21. }
    22.  
    23. bool ClientSocket::connectToHost(QString host, int port)
    24. {
    25. if (port == 0) return false;
    26. m_socket->connectToHost(host, port);
    27. return m_socket->waitForConnected(1000);
    28. }
    29.  
    30. void ClientSocket::write(const char* Data,unsigned int nBytes)
    31. {
    32. if (m_socket && (m_socket->state() == QAbstractSocket::ConnectedState))
    33. {
    34. m_socket->write(Data);
    35. m_socket->flush();
    36. }
    37. }
    38.  
    39. void ClientSocket::test()
    40. {
    41. stop();
    42. }
    43.  
    44. void ClientSocket::run()
    45. {
    46. exec();
    47. }
    To copy to clipboard, switch view to plain text mode 
    At some place in some thread this class is instantiated in constructor like this:
    Qt Code:
    1. SomeClass::SomeClass()
    2. : m_ClientSocket()
    3. {
    4. bool bConnected = m_ClientSocket.connectToHost("localhost", 1000);
    5. if (bConnected)
    6. {
    7. m_ClientSocket.write("rtst", 4);
    8. }
    9. }
    To copy to clipboard, switch view to plain text mode 
    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?

  2. #2
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    131
    Thanks
    11
    Thanked 16 Times in 16 Posts
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default 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?

  3. #3
    Join Date
    Sep 2010
    Posts
    22
    Thanks
    4
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows Maemo/MeeGo

    Default 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.

  4. #4
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    131
    Thanks
    11
    Thanked 16 Times in 16 Posts
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default 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)

  5. #5
    Join Date
    Dec 2008
    Location
    France
    Posts
    93
    Thanked 23 Times in 22 Posts
    Qt products
    Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android

    Default 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 :
    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/.

  6. #6
    Join Date
    Sep 2010
    Posts
    22
    Thanks
    4
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows Maemo/MeeGo

    Default 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 View Post
    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/.
    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:


    Qt Code:
    1. ClientSocket::ClientSocket()
    2. :m_isRunning(false)
    3. ,m_socket(new QTcpSocket())
    4. {
    5. QThread* t=new QThread();
    6. connect(m_socket, SIGNAL(readyRead()), this, SLOT(test()));
    7. m_socket->moveToThread(t);
    8. t->start();
    To copy to clipboard, switch view to plain text mode 
    This way slot also doesn't get called. And without subclassing QThread I cannot start QThread's event loop because exec() is protected.
    Last edited by R-Type; 20th October 2011 at 16:31.

  7. #7
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    869
    Thanks
    70
    Thanked 59 Times in 57 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default 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).

    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.
    Òscar Llarch i Galán

  8. #8
    Join Date
    Dec 2008
    Location
    France
    Posts
    93
    Thanked 23 Times in 22 Posts
    Qt products
    Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android

    Default 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
    Qt Code:
    1. #include <QtCore/QCoreApplication>
    2. #include "clientsocket.h"
    3.  
    4. #include <QThread>
    5. #include <QtDebug>
    6.  
    7. int main(int argc, char *argv[])
    8. {
    9. QCoreApplication a(argc, argv);
    10.  
    11. ClientSocket m_ClientSocket;
    12. QThread *thread = new QThread(&a);
    13. thread->start();
    14. // now we got another thread
    15. m_ClientSocket.moveToThread(thread);
    16.  
    17. qDebug() << "Main thread is " <<QThread::currentThreadId();
    18.  
    19. bool bConnected = m_ClientSocket.connectToHost("10.33.17.37", 8000);
    20. qDebug() << "Connexion done";
    21. if (bConnected)
    22. {
    23. qDebug() << "Ask for Id";
    24. m_ClientSocket.write("*rem\n*idn?\n", 10);
    25. }
    26.  
    27. // For testing don't do a exec() just wait for msec
    28. // Without the processEvent() qDebug not displaying anything but
    29. // the threadid prove the reception is done in the other thread
    30. thread->wait(500); // After 500ms I should have the response or I give up.
    31. a.processEvents();
    32. thread->quit();
    33. thread->wait(100);
    34. return 0;
    35. }
    To copy to clipboard, switch view to plain text mode 

    clientsocket.h
    Qt Code:
    1. #ifndef CLIENTSOCKET_H
    2. #define CLIENTSOCKET_H
    3.  
    4. #include <QTcpSocket>
    5.  
    6. class ClientSocket: public QObject
    7. {
    8. Q_OBJECT
    9.  
    10. public:
    11. ClientSocket();
    12. bool connectToHost(QString host, int port);
    13. void write(const char* Data,unsigned int nBytes);
    14. //void run();
    15. public slots:
    16. void test();
    17.  
    18. private:
    19. QTcpSocket* m_socket;
    20. };
    21.  
    22.  
    23. #endif // CLIENTSOCKET_H
    To copy to clipboard, switch view to plain text mode 


    clientsocket.c
    Qt Code:
    1. #include "clientsocket.h"
    2.  
    3. #include <QDebug>
    4. #include <QThread>
    5.  
    6. ClientSocket::ClientSocket() : QObject()
    7. ,m_socket(new QTcpSocket())
    8. {
    9. connect(m_socket, SIGNAL(readyRead()), this, SLOT(test()), Qt::QueuedConnection);
    10. }
    11.  
    12. bool ClientSocket::connectToHost(QString host, int port)
    13. {
    14. if (port == 0) return false;
    15. m_socket->connectToHost(host, port);
    16. return m_socket->waitForConnected(1000);
    17. }
    18.  
    19. void ClientSocket::write(const char* Data,unsigned int nBytes)
    20. {
    21. if (m_socket && (m_socket->state() == QAbstractSocket::ConnectedState))
    22. {
    23. m_socket->write(Data);
    24. m_socket->flush();
    25. }
    26. }
    27.  
    28. void ClientSocket::test()
    29. {
    30. qDebug() << "I got something here!!!" << QThread::currentThreadId() ;
    31. }
    To copy to clipboard, switch view to plain text mode 

    This is the output:
    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

  9. #9
    Join Date
    Sep 2010
    Posts
    22
    Thanks
    4
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows Maemo/MeeGo

    Default Re: QTcpSocket: no readyRead() signal even in Qthread event loop

    Quote Originally Posted by ^NyAw^ View Post
    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^ View Post
    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.
    Last edited by R-Type; 21st October 2011 at 12:22.

  10. #10
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    869
    Thanks
    70
    Thanked 59 Times in 57 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QTcpSocket: no readyRead() signal even in Qthread event loop

    Hi,

    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.

    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?
    Qt Code:
    1. void myThread::run()
    2. {
    3. ...
    4. //create the socket here
    5. exec(); //The thread enters into the eventLoop, so the next line of code only will be called when you stop the thread.
    6. //delete the socket here, ore close connection, ...
    7. }
    To copy to clipboard, switch view to plain text mode 
    Òscar Llarch i Galán

  11. #11
    Join Date
    Sep 2010
    Posts
    22
    Thanks
    4
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows Maemo/MeeGo

    Default Re: QTcpSocket: no readyRead() signal even in Qthread event loop

    Quote Originally Posted by ^NyAw^ View Post
    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^ View Post
    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...

  12. #12
    Join Date
    Sep 2010
    Posts
    22
    Thanks
    4
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows Maemo/MeeGo

    Default 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:
    Qt Code:
    1. m_socket->write(Data);
    2. m_socket->flush();
    3. m_socket->waitForBytesWritten();
    4. qApp->processEvents();
    5. bool hasData=m_socket->waitForReadyRead();
    6. int num=m_socket->bytesAvailable();
    7. QByteArray data=m_socket->readAll();
    8. qDebug()<<num<<data;
    To copy to clipboard, switch view to plain text mode 
    hasData is true and I can read my data. After that test() slot, connected to readyRead() is called. BUT if I comment
    Qt Code:
    1. bool hasData=m_socket->waitForReadyRead();
    To copy to clipboard, switch view to plain text mode 
    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.

  13. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default 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.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  14. #14
    Join Date
    Sep 2010
    Posts
    22
    Thanks
    4
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows Maemo/MeeGo

    Default 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.
    Qt Code:
    1. class ClientSocket : public QObject {
    2. Q_OBJECT
    3. public:
    4. ClientSocket() : QObject()
    5. , m_socket(new QTcpSocket(this)) {
    6. connect(m_socket, SIGNAL(readyRead()), this, SLOT(test()));
    7. }
    8. virtual ~ClientSocket() {};
    9. bool connectToHost(QString host, int port) {
    10. m_socket->connectToHost(host, port);
    11. return m_socket->waitForConnected(1000);
    12. }
    13. void write(const char* Data,unsigned int nBytes) {
    14. if (m_socket && (m_socket->state() == QAbstractSocket::ConnectedState))
    15. {
    16. m_socket->write(Data);
    17. m_socket->flush();
    18. m_socket->waitForBytesWritten();
    19. //bool hasData=m_socket->waitForReadyRead();
    20. //int num=m_socket->bytesAvailable();
    21. //QByteArray data=m_socket->readAll();
    22. //qDebug()<<num<<data;
    23. }
    24. }
    25. public slots:
    26. void test() { qDebug()<<"readyRead()"; }
    27. private:
    28. QTcpSocket* m_socket;
    29. };
    To copy to clipboard, switch view to plain text mode 
    From DLL code it's used like this
    Qt Code:
    1. SomeClass::SomeClass() : m_ClientSocket() {
    2. bool bConnected = m_ClientSocket.connectToHost("localhost", 1000);
    3. if (bConnected) m_ClientSocket.write("rtst", 4);
    4. }
    To copy to clipboard, switch view to plain text mode 
    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...
    Last edited by R-Type; 25th October 2011 at 09:11.

  15. #15
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTcpSocket: no readyRead() signal even in Qthread event loop

    Quote Originally Posted by R-Type View Post
    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.

    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.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  16. #16
    Join Date
    Sep 2010
    Posts
    22
    Thanks
    4
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows Maemo/MeeGo

    Default Re: QTcpSocket: no readyRead() signal even in Qthread event loop

    Quote Originally Posted by wysota View Post
    The main thread also has (or at least can have) an event loop
    In application (plugin) where it doesn't work, call to ClientSocked takes place not from the main thread. And in example above, where I use ClientSocket from main(), it works.
    Quote Originally Posted by wysota View Post
    Sure, but you are calling the socket's functions directly from the main thread which is forbidden.
    You are right, connect and write had to be called also in run in this example.

  17. #17
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTcpSocket: no readyRead() signal even in Qthread event loop

    No, connect() can be called anywhere. The point is not to call any of the methods of objects belonging to thread B from thread A. Regardless of whether there are slots involved anywhere.

    So this is forbidden:
    Qt Code:
    1. ClientSocket* c=new ClientSocket();
    2. c->start();
    3. Sleep(10000); // doesn't make sense
    4. bool bConnected = c->connectToHost("localhost", 1000); // forbidden
    To copy to clipboard, switch view to plain text mode 

    and if you change those calls to proper ones (using signals and slots), you'll notice there is no advantage of having a thread anywhere, it only causes trouble. Qt works in asynchronous fashion, when you try to force it to be synchronous (like in your code above), you'll have more problems with it than benefits from not having to switch your thinking into asynchronous mode.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. Replies: 1
    Last Post: 22nd July 2010, 09:16
  2. Terminate a QThread with an event loop
    By paolom in forum Qt Programming
    Replies: 2
    Last Post: 12th May 2010, 11:53
  3. QThread event loop blocking the GUI
    By JoeMerchant in forum Qt Programming
    Replies: 4
    Last Post: 18th July 2009, 07:54
  4. QThread event loop seems blocked
    By eurodatar in forum Qt Programming
    Replies: 3
    Last Post: 6th May 2009, 16:50
  5. Workload in a QThread blocks main application's event loop ?
    By 0xBulbizarre in forum Qt Programming
    Replies: 14
    Last Post: 9th April 2006, 21:55

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.