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

Justin Karneges justin at affinix.com
Sun Sep 9 20:16:00 CEST 2012


Hi,

It is not possible to know what TCP data has been acked through QTcpSocket 
alone. The bytesWritten signal is more for flow-control. Generally speaking, 
TCP is designed to make it easier to send data, but TCP alone is generally not 
a solution for reliable transmission. It is possible to detect successful 
socket closure, but not successful writes of individual bytes/packets. 
Protocols that need mid-stream reliability usually introduce their own ACKing 
layer. So, if you want Client A to know if Client B has received some data, 
then you should program Client B to send some acknowledgement information to 
Client A.

That said, depending on the operating system it may be possible to peek around 
at underlying state using non-Qt methods. For example, on Linux you can 
examine the size of your send queue by doing an ioctl() for SIOCOUTQ. However, 
nobody really does this, because protocols intendend to be reliable between 
network peers of any platform already have an ACKing layer added.

Hope that helps.

On Sunday, September 09, 2012 11:01:51 AM d3fault wrote:
> 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
> case?
> 
> 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
> 
> d3fault
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/interest



More information about the Interest mailing list