Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QTcpSocket and QThread



  • Hi,i am learing qt programing and i trying to make basic chat server with QThread and QTcpServer.
    I have this error:
    QObject: Cannot create children for a parent that is in different thread.
    (Parent is QNativeSocketEngine(0x3b77c8), parent's thread is myThread(0xa0df70), current thread is QThread(0x3b2d38).

    My code is :
    chatserver.cpp:

    #include "chatserver.h"
    
    
    
    chatServer::chatServer(QObject *parent)
    {
        hash=new QHash<qintptr,myThread*>;
        h_nicks=new QHash<qint32,QString>;
        //connect(client,SIGNAL(sendMessage(QByteArray)),this,SLOT(allSendMessage(QByteArray)),Qt::AutoConnection);
    }
    
    void chatServer::startServer()
    {
        if(this->listen(QHostAddress::Any,1213)){
            qDebug()<<"Server started";
        }else{
            qDebug()<<"Server could not be started";
        }
    }
    
    void chatServer::incomingConnection(qintptr handle)
    {
        qDebug()<<"Incoming connection "<<handle;
        client=new myThread(handle,h_nicks,this);
        hash->insert(handle,client);
        connect(client,SIGNAL(finished()),client,SLOT(deleteLater()));
        connect(client,SIGNAL(sendMessage(QByteArray)),this,SLOT(allSendMessage(QByteArray)),Qt::AutoConnection);
        client->start();
    }
    
    void chatServer::allSendMessage(QByteArray array)
    {
        qDebug()<<"Test!!!!";
        foreach (qintptr i, hash->keys()) {
            hash->value(i)->getMessage(array);
        }
    }
    

    chatserver.h:

    #ifndef CHATSERVER_H
    #define CHATSERVER_H
    
    #include <QObject>
    #include <QTcpServer>
    #include "mythread.h"
    #include <QHash>
    
    
    class chatServer : public QTcpServer
    {
        Q_OBJECT
    public:
        explicit chatServer(QObject *parent = 0);
        void startServer();
    protected:
        void incomingConnection(qintptr handle);
    public slots:
        void allSendMessage(QByteArray array);
    private:
        QHash<qintptr,myThread*> *hash;
        myThread *client;
        QHash<qint32,QString> *h_nicks;
    };
    
    #endif // CHATSERVER_H
    

    mythread.cpp:

    #include "mythread.h"
    
    
    myThread::myThread(qintptr id,QHash<qint32,QString> *hnick, QObject *parent)
    {
        this->socketDescriptor=id;
        h_nicks=hnick;
    
    
    
    }
    
    void myThread::run()
    {
        qDebug()<<"Starting threadh_nick id "<<this->socketDescriptor;
        socket=new QTcpSocket;
        qDebug()<<"1";
        if(!socket->setSocketDescriptor(this->socketDescriptor)){
            qDebug()<<socket->error();
            return;
        }
    
        connect(socket,SIGNAL(readyRead()),this,SLOT(readyRead()),Qt::DirectConnection);
        connect(socket,SIGNAL(disconnected()),this,SLOT(disconnected()),Qt::DirectConnection);
    
        qDebug()<<"Client connect to "<<this->socketDescriptor;
    
        exec();
    }
    
    void myThread::getMessage(QByteArray array)
    {
        qDebug()<<array;
        //socket->write(array);
        //socket->waitForReadyRead();
        this->socket->write(array);
    
    }
    
    void myThread::readyRead()
    {
        qint32 messageType;
        QByteArray in=socket->readAll();
        QDataStream in_d(&in,QIODevice::ReadOnly);
        in_d>>messageType;
        qDebug()<<messageType;
        if(messageType==2){
            in_d>>nick;
            qDebug()<<nick;
            h_nicks->insert(this->socketDescriptor,nick);
        }else{
        QByteArray array;//=socket->readAll();
        QDataStream buffer(&array,QIODevice::ReadWrite);
        qint32 messageSender;
        messageSender=this->socketDescriptor;
        buffer<<messageSender;
        QString readSocket;
        in_d>>readSocket;
        buffer<<readSocket;
        qDebug()<<this->socketDescriptor<<" "<<array;
        emit sendMessage(array);
        }
    }
    
    void myThread::disconnected()
    {
    
        socket->deleteLater();
        exit(0);
    }
    

    mythread.h :

    #ifndef MYTHREAD_H
    #define MYTHREAD_H
    
    #include <QObject>
    #include <QTcpSocket>
    #include <QThread>
    #include <QDebug>
    #include <QAbstractSocket>
    #include <QDataStream>
    #include <QString>
    
    class myThread : public QThread
    {
        Q_OBJECT
    public:
       explicit myThread(qintptr id,QHash<qint32,QString> *hnick,QObject *parent=0);
        void run();
        void getMessage(QByteArray array);
    private:
        QTcpSocket *socket;
        qintptr socketDescriptor;
        QString nick;
        QHash<qint32,QString> *h_nicks;
    public slots:
        void readyRead();
        void disconnected();
    signals:
        void sendMessage(QByteArray array);
    };
    
    #endif // MYTHREAD_H
    

    Can someone explain me how is right way to do multi thread socket programming?
    Thanks for help.

    [edit: added missing coding tags ``` SGaist]


  • Lifetime Qt Champion

    Hi,

    One thing I can see is that you don't call the base class constructor in any of your sub-classes.

    Note that if you are beginning programming, dealing with threads first for might not be the best idea



  • Hi, thanks for advice, i change my application server, so i dont use threads.
    Now what is proper way to close socket.
    In incomingconnections i have QHash and i insert socketdescriptor as key in that hash and socket pointer as value.
    Then i connect socket readyRead and disconnected signals with my slots.
    But in disconnected slot i have this code:
    QTcpSocket m_socket=static_cast<QTcpSocket>(sender());
    and when i put this qDebug()<<m_socket->socketDescriptor() i got result -1.
    Because i got result -1 i cant delete socket from my QHash?
    Where i make mistake?
    Btw code from above works in slot readyRead.

    Thanks for help.
    [edit]
    Sorry, but i found what is my problem. I was using socketDescriptor as key in hash but i should use QTcpSocket as keys in QHash.


  • Lifetime Qt Champion

    You should also use qobject_cast rather than static_cast, static cast doesn't do any check so you might be casting to something invalid.


Log in to reply