Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QTcpSocket and QThread
Forum Updated to NodeBB v4.3 + New Features

QTcpSocket and QThread

Scheduled Pinned Locked Moved General and Desktop
4 Posts 2 Posters 3.5k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    Sasha
    wrote on last edited by SGaist
    #1

    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]

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      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

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • S Offline
        S Offline
        Sasha
        wrote on last edited by Sasha
        #3

        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.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          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.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved