[Qt-interest] problem using sockets and threads
Thiago Macieira
thiago at kde.org
Tue Feb 8 17:24:17 CET 2011
Em terça-feira, 8 de fevereiro de 2011, às 15:40:06, pmqt71 escreveu:
> Hi,
> I'm writing a client server app and have a problem on the server side.
> Like a producer/consumer pattern, the server creates 1 thread for each
> connected socket/client and 1 consumer thread to manage the requests.
> The problem is that at one point the socket readyRead signal (server
> side) is not fired anymore. These are the steps:
You probably have thread affinity errors. Your QTcpSocket classes are not affined
with the threads where you're doing your reads and writes from.
Why do you need one thread per socket and one thread per request? Isn't that
wasteful? If you have threads per requests anyway, the socket I/O isn't
blocked by the operation. One thread for all sockets should be enough.
> 1) ClientConnectionThread runs on the server side and handles a client
> socket (one instance per connected client). In the run method I
> connect the readyRead signal and then call exec().
Did you remember to moveToThread the socket to that thread before you started
it? If you forgot that, then the readyRead() signal was queued.
You *MUST* *NOT* touch the QTcpSocket object from any thread that is not the
object's thread. This will cause weird issues (like readyRead not firing) or
crashes.
> 4) ConsumerThread gets the request from the queue, processes it and
> answers to the client posting a custom event (having the answer as
> data member) on the ClientConnectionThread
On the thread class itself? Remember that the QThread object's thread affinity
is to the thread that started it, not the thread it started. So the events are
processed in that original thread.
You should post the event to an object that is running in the thread, not to
the thread.
> 5) ClientConnectionThread gets the custom event in the event method,
> gets the answer and write it to the connected socket.
> -- this request/response is OK --
If you didn't get the threading right, it's not. Though in this case, if you
made two mistakes (like it sounds that you did), then one will cancel out the
other and the writing is actually ok.
> 8) the client receives the data correctly, all seems OK.
> Now the problem: if the client sends a request to the server,
> ClientConnectionThread::onReadyRead is not fired. It seems that the
> ClientConnectionThread event loop is not running properly.
>
> Is there something wrong (or all) in the design causing a problem in the
> thread?
Yes. In my opinion (opinion!), the design is completely wrong. You're using
threads for sockets when you don't need to.
> same code:
>
> void ClientConnectionThread::run()
> {
> m_tcpSocket = new QTcpSocket();
> if (!m_tcpSocket->setSocketDescriptor(m_socketDescriptor)) {
> emit error(m_tcpSocket->error());
> return;
> }
>
> connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
> connect(m_tcpSocket, SIGNAL(disconnected()), this,
> SLOT(onSocketDisconnect()));
>
> exec();
> }
Never put slots in a class derived from QThread, unless you know what you're
doing. This also extends to posting events to that class.
Also, never moveToThread(this).
http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/
> bool ClientConnectionThread::event(QEvent *ev)
> {
> if(ev->type() == QDataEvent::DataEventType)
> {
> QDataEvent *dataEvent = static_cast<QDataEvent *>(ev);
> //only this thread handles the socket
> writeToSocket(m_tcpSocket, dataEvent->data().toString());
> }
> return QThread::event(ev);
> }
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Senior Product Manager - Nokia, Qt Development Frameworks
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 190 bytes
Desc: This is a digitally signed message part.
Url : http://lists.qt-project.org/pipermail/qt-interest-old/attachments/20110208/b9294f0a/attachment.bin
More information about the Qt-interest-old
mailing list