[SOLVED] QTcpSocket Threading issue...



  • I am trying to create a QTcpSocket in a thread in which just reads and writes data from a server...I know my restrictions are that I need to create the socket within my thread. My thread is in a 20 mS loop if connected and the loop time changes with respect to the TcpSocket state. Heres the run() in my QThread.

    Note: globalTcpState is set to SOCK_CONNECT.

    @
    /*
    // main tcp loop
    */
    void clsTcpThread::run()
    {

    // tcp socket instantiation
    QTcpSocket *tcpSocket = new QTcpSocket(this);
    
    // inifinite loop...
    threadBool = true;
    while (threadBool){
        // state machine for connection state
        switch(globalTcpState){
    
        /*
        //  connect to server
        */
        case SOCK_CONNECT:
    
            // check connection state
            if (tcpSocket->state() == QTcpSocket::ConnectedState){
                qDebug() << "111 Connected to host " << tcpConn.IPAddress << " on port " << tcpConn.port;
                globalTcpState = SOCK_CONNECTED;
            }
            else if (tcpSocket->state() == QTcpSocket::ConnectingState){
                qDebug() << "111 Connecting to host.. " << tcpConn.IPAddress << " on port " << tcpConn.port;
                globalTcpState = SOCK_CONNECT;
            }
            else if (tcpSocket->state() == QTcpSocket::UnconnectedState){
                qDebug() << "Failed to connect to host " << tcpConn.IPAddress << " on port " << tcpConn.port << "... reconnecting";
                tcpSocket->close();  // close socket for safe measures...
    
                // connect to host...
                tcpSocket->connectToHost(tcpConn.IPAddress, QString(tcpConn.port).toInt());
    
                globalTcpState = SOCK_CONNECT;
            }
    
            break;
    
        /*
        //  connected to server
        */
        case SOCK_CONNECTED:
    
            // read the socket every 20 mS
            bytesAvail = tcpSocket->bytesAvailable();
            if (bytesAvail == 9){
                 // read data...
            }
            else {
                qDebug() << "Odd amount of bytes available" << bytesAvail;
            }
    
            break;
    
    
        /*
        //  disconnect from server
        */
        case SOCK_DISCONNECT:
    
            // disconnect from host
            tcpSocket->disconnectFromHost();
            globalAppState = SOCK_CONNECT;
            qDebug() << "Disconnected from host " << tcpConn.IPAddress << " on port " << tcpConn.port;
    
            break;
        }
    
        // delay state machine
        switch (globalAppState){
        case SOCK_CONNECT:
            this->msleep(1000);
            break;
        case SOCK_CONNECTED:
            this->msleep(20);
            break;
        case SOCK_DISCONNECT:
            this->msleep(1000);
            break;
        }
    
    }
    

    }
    @

    the issue is that the socket goes into connecting state from the server side and says its connected, but the QTcpSocket created within the thread is not going into connected state... This leads me to think that the return from the accept is not recieved by the socket created in the thread... (possibly a socket state event issue?)

    Any help would be great.



  • Why do not you use the functions waitForConnected(), waitForReadyRead(), waitForDisconnected(), waitForBytesWritten()?



  • I have tried to implement waitForConnected() after my connect to host statement and unfortunately the socket still stays in connecting state for some reason...

    I moved it to my main gui thread and just used a ready read signal and tcpsocket state change signal and it works fine, I really want this in a thread though since there are many things that will be updating on the main thread.



  • You need to have an event loop running in your worker thread for sockets and other event driven objects to work properly.

    Recommended pattern is to put your logic inside of a QObject sub-class and either create that in your thread's run function and then call QThread::exec() or just use a standard QThread object and use moveToThread() to push your worker QObject into the context of your worker thread.



  • Please read "this wiki article":http://qt-project.org/wiki/Threads_Events_QObjects to gain an understanding of currently recommended way of using threads in Qt applications.



  • ZapB, thats exactly what I am looking to do. I have tried this before and failed to get the events working in the thread... is there an example included in the QtSDK that shows how to do this? Probably not with a QTcpSocket, but with another object of that matter?

    Thanks!



  • Subclass QTcpSocket, add slots, connect the signals with the slots in the ctor.

    In the QThread::Run:
    @
    {
    MyQTcpSocket tcpsocket;
    exec();
    }@

    You need to call exec() to catch the signals. If your have a while loop before exec() you will not get to the exec() function and your slots will not be called.



  • Is this possible with widget classes as well?

    I am just using a Qwt Plot as well as 3 realtime updating dials showing the values of the lines on the plot. I have a lot updating so I am trying to thread when possible and I wasnt sure if I could update my custom dial widget from a thread or not...

    The wiki article was very helpful as well.

    Thanks!


  • Moderators

    You can't directly touch anything GUI-related from any thread except the main thread.



  • Right, well thank you. my problem is solved! Much appreciated.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.