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
 

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