c++ - QTcpSocket in a thread doesn't always send data instantly -
i have server handles every client connection in separate thread. test it, implemented simple "echo" service: type message client, sent server, server sends back, , client displays it.
as send short packets, use single write , read current tests, never had split packets.
the client uses write()
, readall()
, works time (verified packet sniffer tool)
what observe time, server sends packets @ every second occasion.
for example:
- the client sends "abc"
- the server receives it, sends back.
write()
function returns 3. - the client receives nothing. check packer sniffer, no packets sent
- the client sends "def", several seconds, or minutes later
- the server receives it, sends back.
write()
function returns 3. - the client receives both "abc" , "def" messages. 90% of time 2 separate packets, 10% of time "abcdef".
on rare occasions, 1 message enough. of time, however, second message needed send both first , second message.
an example of client's debug output, indicating sent , received (note client sends typed in manually, , between each message waited @ least 10 seconds):
client: 1 client: 2 server: 1 server: 2 client: 12345 server: 12345 client: abc client: def server: abcdef client: 123 server: 123 client: 456 client: 789 server: 456789 client: server: client: b client: c server: b server: c
i know tcp 1 continuous stream, wasn't expecting on unburdened lan should take minutes transmit few bytes. interestingly, client can send correctly , instantly, never waits further writes glue them together.
as client seems work perfectly, i'm suspecting wrong threads.
once qtcpserver
receives incoming connection, start new thread, passing socketdescriptor thread's constructor.
tcpthread::tcpthread(int socketdescriptor, qobject *parent) : qthread(parent) { this->socketdescriptor = socketdescriptor; } void tcpthread::run() { if (!tcpsocket->setsocketdescriptor(socketdescriptor)) { qdebug() << tcpsocket->error(); return; } connect(tcpsocket, signal(readyread()), this, slot(read_data())); while (tcpsocket->state() == qabstractsocket::connectedstate) { tcpsocket->waitfordisconnected(-1); } } void tcpthread::read_data() { qbytearray data = tcpsocket->readall(); int nr = tcpsocket->write(data); qdebug() << data << " (" << nr << " bytes written)"; }
i know, not best practice of handling threads, used "qt4 approach" quick familiarization qtcpsocket.
what interesting, receive warnings @ each call write()
:
qsocketnotifier: socket notifiers cannot enabled or disabled thread
i wonder why. created instance of qtcpsocket
in run()
method of thread, should in same thread, shouldn't it?
indeed, if move instantiation of socket constructor, get
qobject: cannot create children parent in different thread. (parent qtcpsocket(0x2c54a80), parent's thread qthread(0x10776d0), current thread tcpthread(0x2c53c18)
which didn't before. however, instantiation in constructor, code works same: message sent instantly, glued , sent next message, no matter how time passes between two.
what doing wrong?
using thread qtcpsocket
s pointless. asynchronous api gain using thread minimal (problem may when have other time consuming job blocks event loop).
another problem way creating objects , assign them threads. you've given perfect link topic didn't understand it.
simple rules when using threads in qt:
- never assign thread itself
- you can move objects between threads if don't have parent (it root of memory structure tree, whole 3 moved new thread)
- setting parent assigns object parent thread
- default connections of slots , signals detects signal emitted different thread receiver assigned to, in such case signal wrapped , passed proper thread using event loop.
- if using value objects in signal slots don't need synchronization (locks , mutexes)
- when override
qthread::run()
, using signals , slots should run event loop in thread, either callingqthread::exec()
or creating new event loop.
so in general have lots of mistakes in code. recomand abandon qthread
or @ least read article again understand , apply recommendations (it written before qt5 released, claim "qt4 style" invalid).
Comments
Post a Comment