QTcpSocket in an own Thread
-
Hello folks,
I implemented a threaded TCP Server (which I mostly copied from the Threaded Fortune Server example). It should run all the time and spawn new Threads for each Connection. These take everything incoming, process the commands asynchronously and answer the client. Here is a minimal example of how I implemented this:
@class Server : public QTcpServer {
Server();
protected:
void incomingConnection(int socketDesc);
}Server::Server() : QTcpServer() {
this->listen(QHostAddress::Any, PORT);
}void Server::incomingConnection(int socketDescriptor) {
ServerThread *t = new ServerThread(socketDescriptor);
t->start();
}class ServerThread : public QThread {
ServerThread(int socketDescriptor);
protected:
void run();
public slots:
void writeData(QString data);
private:
int m_socketDescriptor;
QTcpSocket *m_socket;
}ServerThread::ServerThread(int socketDescriptor) : QThread(), m_socketDescriptor(socketDescriptor) {}
void ServerThread::run() {
m_socket = new QTcpSocket();
m_socket->setSocketDescriptor(m_socketDescriptor);
exec();
}void ServerThread::writeData(QString data) {
m_socket->write(data.toAscii());
}
@Now I connect another class (which is in another Thread as the ServerThread) to the readyRead() signal of the socket (I let this signal come through my ServerThread class - not shown in the Code). This class processes the input, this might take some time. The result should then be passed to the Socket and written to the client. So I wrote a signal in my class and connected this to the writeData() slot (I tried Auto as well as Queued Connection). As soon as I call m_socket->write() I get the following error:
QObject: Cannot create children for a parent that is in a different thread. (Parent is QNativeSocketEngine(0x12f0f70), parent's thread is ServerThread(0xfbbae8), current thread is QThread(0xfa7c48)Any idea how I can avoid this?
Best Regards,
Tobias -
The error should be clear enough.
A couple of tips:
You do not need threads for TCP communication.
Your usage of QThread is very wrong. The QThread object lives in the main thread, so, all slots are called from within the main thread, not the thread you think it is called. In other words, the writeData slot is not performed inside your new thread. There are a few techniques to solve this. One is to create a new QObject subclass, create an object from this new subclass, create a QThread object and move the complete subclass object to the QThread object.
-
Hmm.. yes, there I was wrong..
I knew that the QThread object lives in the main thread or the thread where it was created. This is why I instanciated QTcpSoket from inside the run() method, that it is "born" in my new Thread.
But I thaught, that the eventloop which is started with exec() dispatches all signals/slots connected to the Thread. So this is only true for QObjects created inside my thread emitting signals?
So when I emit a signal from main thread connected to the writeData() slot it will be called in main thread. But when I would emit a signal from, lets just say QTcpServer would be my own class, within the Thread it would go through the event loop of this Thread or not?Thanks!
I try tomorrow when I am back at work ;) -
-
[quote]All of QT’s TCP and UDP higher level classes throw all data into a seperate thread anyways so you shouldn’t need to put this functions into a another thread.[/quote]
Which higher level classes are you talking about? The statement is simply false for QTcpSocket/QUdpSocket.