Sending and Recieving QTcpSocket in different threads
-
I am looking to design a high traffic server using Qt's QTcpServer. The flow of the current design is the following:
TcpReciever(QTcpServer) => DatabaseClass(QObject) => TcpSender(QObject)
The DatabaseClass and TcpSender are run in their own thread.
The information is passed between threads through signals/slots. ie:
@connect(this, SIGNAL(sendInfo(QTcpSocket*,int)),
databaseClass, SLOT(infoFromReciever(QTcpSocket*,int)),
Qt::QueuedConnection);@After writing out to the socket, I get the following error despite all of my code executing correctly, and continuing to run correctly:
QObject: Cannot create children for a parent that is in a different thread. (Parent is QNativeSocketEngine(0xe489c0), parent's thread is QThread(0xe30890), current thread is QThread(0xe49a00)
@OTextStream os(socket);
os << "HTTP/1.0 200 Ok\r\n"
"Content-Type: text/html; charset="utf-8"\r\n"
"\r\n" << infoString.c_str() << "\n";
socket->deleteLater();@This is the bulk of my TcpSender, the error comes after the function is executed.
Does anyone have any idea why my error is happening. I am guessing that there is a signal being emitted(possibly when the QTcpSocket is being deleted, or is trying to be deleted). Or is there something wrong with my design, and all TCP I/O should be done in the same thread(QTcpServer).
Thank you
-
QTcpSocket like most QObject derived classes is NOT thread-safe. What you are doing can lead to potential disaster as the backend implementation (QNativeSocketEngine) was not designed to do what you want, and it explicitely tells you so.
If you really want to prepare the answer in another thread (which I understand is the costly operation), you should use the QByteArray versions of QTextStream and then use a queued signal/slot to have the main thread perform the write of this buffer on your behalf on the connection.
You can even use nice frameworks like QtConcurrent which will manage a clean threadpool for you.