[Interest] TCP ACK with QDataStream -- OR: disconnect race condition detection

d3fault d3faultdotxbe at gmail.com
Sun Sep 9 20:01:51 CEST 2012

So after some more reading/testing, I'm starting to think
QIODevice::bytesWritten(qint64) might be what I'm looking for... but I
am unable to confirm it.

There's only one tiny snippet in the QAbstractSocket docs that
indicate the bytesWritten(qint64) might be a TCP ACK for that amount
of bytes: "The bytesWritten() signal is emitted when data has been
written to the socket (i.e., when the client has read the data)" [0].
However, the very next sentence makes me think that
bytesWritten(qint64) is emitted only when the bytes are written to the
local internal buffer: "Note that Qt does not limit the write buffer
size. You can monitor its size by listening to [the bytesWritten
signal]". Perhaps on socket types other than QTcpSocket this is the

Just by looking at the documentation, I can't figure out if the qint64
that QIODevice::write() returns is how much has been written to the
local internal buffer, or if that's bytesWritten()'s job.

I did do some testing to try to figure out what is what, and found
that QIODevice::write() always returns the size of the QByteArray you
send it, even when QAbstractSocket::state() is in UnconnectedState.
>From that alone, I'm guessing that means QIODevice::write() is
responsible for telling us how much was written to the local internal
buffer... and maybe that QIODevice::write() isn't returning -1 when
QAbstractSocket::state() is in UnconnectedState is a bug (that may be
fixed in HEAD, no idea)?

Continuing the testing, I wrote 2 'messages' to the QTcpSocket, and on
the reader side of things only read in one of them. I got this idea
from the snippet in QAbstractSocket's docs: "i.e., when the client has
read the data". To my disappointment, bytesWritten() was emitted on
the sender for both of the messages (it was only emitted once and the
qint64 was the sum of the two message sizes). For my next test, I sent
the first message, closed/disconnected the receiver, then sent the
second message. This time bytesWritten() only showed that the first
message was delivered. That does look somewhat promising, but without
knowing what's really going on it only tells me about as much as
checking QAbstractSocket::isValid() and QAbstractSocket::state() ==
ConnectedState after writing (as mentioned in my previous email). I
can't know that it doesn't simply mean that the bytes were 'sent' [but
not yet ACK'd].

A random guess: does bytesWritten() get triggered by a TCP ACK sent by
the _receiver's_ internal buffer (regardless of whether my code has
read it in or not yet (if I just ignore the readyRead()))? That would
explain why my write 2 messages / read 1 message test above triggered
bytesWritten for BOTH of the messages, if that was the case.

I tried looking through the Qt source for an answer, but really
couldn't even find any related code (Ima newb to Qt internals).
qtcpsocket.cpp, qtcpsocket.h, and qtcpsocket_p.h told me nothing.

[0] - http://qt-project.org/doc/qt-4.8/qabstractsocket.html#details


More information about the Interest mailing list