[Interest] TCP ACK with QDataStream -- OR: disconnect race condition detection
konrad at silmor.de
Mon Sep 10 21:43:11 CEST 2012
let's cut it short and come back to your problem.
On Sunday 09 September 2012 20:54:09 d3fault wrote:
> Haha, funny. Reliable doesn't mean reliable. Who knew...
No it is just a different kind of reliable.
TCP reliable: TCP guarantees that you have a stream. Bytes arrive at the
application in the order they were sent (even if packets arrive out of order
in the OS or are dropped) - no gaps, no reordering. The data in the stream is
(reasonably) reliable against mild (non-intentional) line noise (each TCP
packet has a 16bit checksum). Bytes either arrive intact or not at all.
This is were the use of TCP ACK ends - it ensures that you have a stream.
That's it. End of story. (Thiago made much more detailed arguments if you want
to delve into the details - I recommend just accepting it - he knows what he
is talking about.)
Application reliable: you can guarantee that a transaction (as per the
application's definition of transaction) is executed completely or not at all.
You do this with an application level protocol. There is no way around it.
Even if it is a very simple one. See below.
Naive newbie reliable: you can magically ensure that data is transported and
acted on even if it has to cross broken glass bare footed while being shot at
during a power outage. This is unrealistic and physically impossible - if you
want to know the details - read up on entropy, quantum physics and a few other
subjects that waste a lot of development time - or you may just take the word
of people who tried and failed (like me).
> Are you sure it isn't just Qt failing to utilize the TCP protocol
> correctly? I don't mean to question your expertise, as you sound like
> you know what you're talking about, but this quote from wikipedia
> makes it sound like TCP does in fact do mid-stream reliability: "TCP
> primarily uses a cumulative acknowledgment scheme, where the receiver
> sends an acknowledgment signifying that the receiver has received all
> data preceding the acknowledged sequence number" . That plus
> automatic re-transmission of lost packets sounds like exactly what I
> want! How do I get that number in a platform independent manner [and
> make sense of it]?
See above. Qt's utilization of TCP gives you exactly the guarantees that TCP
itself gives you. You have a stream that is reliable on the transport level.
(Reliable = arrives as expected or not at all)
Hence: if QTcpSocket tells you the data is written this means the data is on
its way in the order you wrote it. That's it. No guarantee that it does not
get eaten by a grue before it arrives. If byte N gets eaten on all repeated
attempts, then byte N+1 is dropped as well and the connection breaks.
> I was going to code my own ack layer on top of TCP... but after a few
> designs and reading further into TCP it sounded an awful lot like
> reinventing the wheel. I came up with my own sequence number scheme
> and everything and oh boy TCP really sucks if you're right :-P...
Fortunately you don't need to *reinvent* the wheel. Real honest to god
computer scientists have done that before. All you need to do is read up on
the subject and then build a wheel that fits your cart. ;-)
> An actually-reliable-tcp-socket class (called something else, and
> perhaps based on QAbstractSocket instead?) sounds like it would make a
> great addition to Qt don't you think? Maybe something along the lines
> of QNetworkRequest::Acknowledged() [signal].... though not necessarily
> anything to do with QNAM (especially since the QNetworkReply makes a
> better acknowledgement in that case lol (and now I'm just confusing
No, use TCP socket and use the guarantees it gives you: a stream that arrives
in order with data secured against physical noise.
It does not give you:
1) application transactions
2) security against malicious attackers(1)
3) magical abilities
Let's do this in reverse order: 3 is not achievable in this universe. Let's
drop it. When you write your spec I expect you to write down that your
protocol does not magically overcome disconnected networks.
Security against malicious attackers has been solved before: your interface to
it is QSslSocket (which incidentally also relies on the guarantees of TCP).
From my own experience: do not try to solve this yourself. Use a proven
implementation like QSslSocket. Even if it breaks the SSL experts know better
than the two of us how to fix it.
Finally application transactions. This is where you need to spend some
Define what a message in your application is - a completely transferred file,
an update to the screen,... ; is there just one message in one connection or
do you plan to send many messages in the same stream?
Define a transaction: what actions does the recipient of a message take? Can
the next action be taken even if it is still unclear whether the first one
succeeded? What can go wrong on the transport, during reception, during
processing? What information does the sender need about success or failure?
Your protocol can be as simple as HTTP 0.9: client sends a single line "GET
/myfile.html", server sends the file and then closes the TCP socket. In this
case the client sees from the way the socket is closed whether it received the
entire file (normal close) or something went wrong on the network (error).
It could be a complex concurrent protocol like IMAP: you can put several
requests for folder listings and mail contents into the queue and the server
will respond marking its messages with a tag that allows you to know which
question the answer belongs to. Failed requests do not influence the other
It could be a complex transactional protocol with a strict order of execution,
like the protocols used by databases (a transaction has to succeed or fail
before you start the next one).
What you do not need to do with TCP:
* you do not need to ensure messages arrive in order.
* You do not need to cut messages into packets.
* You do not need to reassemble them.
* You do not need to checksum them against physical defects.
If you use QSslSocket:
* You do not need to implement cryptographic authentication algorithms, you
can use certificates.
* You do not need to secure against malicious attackers altering your data -
SSL does that.
What you do need to do is to define your application layer:
* Define your messages.
* Define your transactions.
* Actually use some form of authentication if applicable.
-------------- next part --------------
An HTML attachment was scrubbed...
-------------- next part --------------
A non-text attachment was scrubbed...
Size: 198 bytes
Desc: This is a digitally signed message part.
More information about the Interest