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