views:

289

answers:

6

When i send()/write() a message over a tcp stream, how can i find out if those bytes were successfully delivered?

The receiver acknowledges receiving the bytes via tcp, so the senders tcp stack should know.

But when I send() some bytes, send() immediately returns, even if the packet could not (yet) be delivered, i tested that on linux 2.6.30 using strace on netcat, pulling my network cable out before sending some bytes.

I am just developing an application where it is very important to know if a message was delivered, but implementing tcp features ("ack for message #123") feels awkward, there must be a better way.

+8  A: 

Having the receiver send back an ack is the best way, even if it "feels awkward". Remember that IP might break your data into multiple packets and re-assemble them, and this could be done multiple times along a transmission if various routers in the way have different MTUs, and so your concept of "a packet" and TCP's might disagree.

Far better to send your "packet", whether it's a string, a serialized object, or binary data, and have the receiver do whatever checks it needs to do to make it it's there, and then send back an acknowledgement.

Paul Tomblin
The facts are right, but I don't like the phrasing. TCP is a reliable protocol, you **will** hear about it if the transmission fails. The fact that you don't need to request an ACK from the remote side is a feature, not a bug. The "best" way to deal with this is to **ignore** the problem at the level of system calls and bytes. If you need a result back, do it at the level of the protocol, not the sockets.
Andy Ross
+6  A: 

The TCP protocol tries very hard to make sure your data arrives. If there is a network problem, it will retransmit the data a few times. That means anything you send is buffered and there is no timely way to make sure it has arrived (there will be a timeout 2 minutes later if the network is down).

If you need a fast feedback, use the UDP protocol. It doesn't use any of the TCP overhead but you must handle all problems yourself.

Aaron Digulla
Yes, by design it is reliable and ordered
RichardOD
+3  A: 

Application layer has no control over the notifications at lower layers (such as the Transport layer) unless they are specifically provided - this is by design. If you want to know what TCP is doing on a per packet level you need to find out at the layer that TCP operates at; this means handling TCP headers and ACK data.

Any protocol you end up using to carry your payload can be used to pass messages back and forth by way of that payload, however. So if you feel awkward using the bits of a TCP header to do this, simply set it up in your application. For instance:

A: Send 450 Bytes
B: Recv 450 Bytes
B: Send 'I got 450 Bytes'
A: Recv 'B got the full message'
A: Continue
ezpz
A: 

This sounds like SCTP could be something to look at; I think it should support what you want. The alternative seems to be to switch to UDP, and if you're switching protocols anyway

Teddy
+7  A: 

The sending TCP does know when the data gets acknowledged by the other end, but the only reason it does this is so that it knows when it can discard the data (because someone else is now responsible for getting it to the application at the other side).

It doesn't typically provide this information to the sending application, because (despite appearances) it wouldn't actually mean much to the sending application. The acknowledgement doesn't mean that the receiving application has got the data and done something sensible with it - all it means is that the sending TCP no longer has to worry about it. The data could still be in transit - within an intermediate proxy server, for example, or within the receiving TCP stack.

"Data successfully recieved" is really an application-level concept - what it means varies depending on the application (for example, for many applications it would only make sense to consider the data "recieved" once it has been synced to disk on the receiving side). So that means you have to implement it yourself, because as the application developer, you're really the only one in a position to know how to do it sensibly for your application.

caf
A: 

Even if it got as far as the TCP layer, there's no guarantee that it didn't sit in the application's buffer, then the app crashed before it could process it. Use an acknowledgement, that's what everything else does (e.g. SMTP)

MarkR