EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

TCP packets : end of thre-way handshake and start of data-transmission - how to detect ?

Started by R.Wieser May 4, 2009
>>> There is no danger of a mix-up: a TCP connection is >>> identified by a set of four numbers: the source IP, >>> destination IP, source port and destination port. >> Hmmm ... thats 12 (IPv4) or 16 (IPv6) bytes only to define a two-way socket. >> As I'm working on a controller with very limited memory (just 2048 *Bytes* >> of RAM, which allso needs to hold the ethernet-packet itself as well as the >> stack) I hoped I could use another method to uniquely identify a connection >> : by (ab)using (a few bits of) the new-to-be-assigned portnumber together >> with the Acknowledge-number. But alas, that idea is now outof the window. > > Is there a specific reason why you insist on implementing TCP/IP with > such small resources ? > > UDP would be much more suitable for such small devices.
"TCP/IP Lean" by Jeremy Bentham shows how to implement a TCP/IP stack on a resource limited system. Andrew
Hello David,

> In that situation you aren't allowed to send data in response > to the ACK of your SYN, because that ACK said the > window size was zero.
Nope, it was not Zero. Initially it was about 8 KByte and the redefinition made it 32 KByte. The packet I did send (after the first ACK) had a payload of 10 bytes.
> Don't use the arrival of a specific packet directly as a trigger > to send.
That is what I'm trying to evade, but as of now I have no clue to when I'm allowed to send, as a Server, my first data-packet. :-(
> Wait until the window size is nonzero before sending.
As mentioned, the first ACK shows a window-size of over 8 KByte, more than enough to receive my data.
> You might want to look at the open source uIP project to get > some implementation ideas. It is designed to be used on very > small systems with limited memory.
Thanks for the hint. But I'm afraid that a Google-search on a generic phrase like that will not turn up much (if anything). Do you have an URL ? Regards, Rudy Wieser -- Origional message David Empson <dempson@actrix.gen.nz> schreef in berichtnieuws 1iz8mix.1g51y2x1mke568N%dempson@actrix.gen.nz...
> R.Wieser <address@not.available> wrote: > > > Hello David, > > > > Thanks for your reply, but somehow I can't seem to extract from it
what I
> > need : > > > > > RFC 793 Section 3.4 (Establishing a connection) says in part: > > <snip quote> > > > > Its not the client actually sending data before it should I'm concerned > > about (as the controller does not have enough RAM to store the data I
will
> > probably just drop the connection), but how figure out which packets to
skip
> > before I'm allowed to send some data myself : Currently I receive two > > different ACK responses to my SYN/ACK (the second packet re-defines the > > window-size). When I send some data after receiving the first ACK the > > client behaves as if I did not send that packet at all (mind you, this
is on
> > a LAN). > > In that situation you aren't allowed to send data in response to the ACK > of your SYN, because that ACK said the window size was zero. The > receiver is allowed to throw away data you send which falls outside the > receiver's window. You must wait until the second ACK which says the > window size is nonzero. > > You could only send data with your responding SYN/ACK or in response to > the client's subsequent ACK if the client had indicated a nonzero window > size in the previous packet, and it seems that most common TCP/IP > implementations never do that during the three-way handshake. > > It occurs to me that the SYN packets are usually also negotiating MSS, > and some TCP implementations may want to wait for MSS to be established > in both directions before reporting their window size. > > > I can ofcourse "fix" this by checking the Acknowledgement-number and as
it
> > did not change re-send the data, but a) would like to know why it does
not
> > respond to my data b) have not enough resources in the controller to
send a
> > packet again anyway. :-\ > > Don't use the arrival of a specific packet directly as a trigger to > send: you should be copying the window size out of the received packets > (strictly it is the range of bytes starting from the ack sequence number > up to the end of the window, and you may need to allow for data you had > previously sent but which the receiver hasn't acknowledged yet). > > Wait until the window size is nonzero before sending. You should also > check that you aren't sending too much data, e.g. the client might open > a very small window initially, preventing you from sending all your > data. In this situation you might not be able to send at all unless the > client opens its window further, unless you send your data in several > small pieces. > > You might want to look at the open source uIP project to get some > implementation ideas. It is designed to be used on very small systems > with limited memory. > > -- > David Empson > dempson@actrix.gen.nz
Hello Paul,

> Is there a specific reason why you insist on implementing > TCP/IP with such small resources ?
I'm an hobbyist. They do normally not need something like a reason to try to do something, do they ? :-) But if you want to know, I've seen several projects implementing the same, and thought it would be a nice project to try for myself. Examples: http://archive.chipcenter.com/circuitcellar/july99/c79bl1.htm http://members.home.nl/bzijlstra/software/examples/RTL8019as.htm
> UDP would be much more suitable for such small devices.
ARP, ICMP (together PING), IP and UDP are allready there. TCP is just the next to be implemented. Regards, Rudy Wieser -- Origional message Paul Keinanen <keinanen@sci.fi> schreef in berichtnieuws fdnvv490sb6a2uvhc1fc7rm1gptcdggrjo@4ax.com...
> On Mon, 4 May 2009 22:06:34 +0200, "R.Wieser" <address@not.available> > wrote: > > >Hello Tauno, > > > >> There is no danger of a mix-up: a TCP connection is > >> identified by a set of four numbers: the source IP, > >> destination IP, source port and destination port. > > > >Hmmm ... thats 12 (IPv4) or 16 (IPv6) bytes only to define a two-way
socket.
> >As I'm working on a controller with very limited memory (just 2048
*Bytes*
> >of RAM, which allso needs to hold the ethernet-packet itself as well as
the
> >stack) I hoped I could use another method to uniquely identify a
connection
> >: by (ab)using (a few bits of) the new-to-be-assigned portnumber together > >with the Acknowledge-number. But alas, that idea is now outof the
window.
> > Is there a specific reason why you insist on implementing TCP/IP with > such small resources ? > > UDP would be much more suitable for such small devices. > > Paul
Hello Andrew,

> "TCP/IP Lean" by Jeremy Bentham shows how to implement a > TCP/IP stack on a resource limited system.
Thanks for the hint. I'll have a look at it. Regards, Rudy Wieser -- Origional message Andrew Jackson <alj@nospam.com> schreef in berichtnieuws Ja-dnW9wW559amLUnZ2dnUVZ8hVi4p2d@eclipse.net.uk...
> >>> There is no danger of a mix-up: a TCP connection is > >>> identified by a set of four numbers: the source IP, > >>> destination IP, source port and destination port. > >> Hmmm ... thats 12 (IPv4) or 16 (IPv6) bytes only to define a two-way
socket.
> >> As I'm working on a controller with very limited memory (just 2048
*Bytes*
> >> of RAM, which allso needs to hold the ethernet-packet itself as well as
the
> >> stack) I hoped I could use another method to uniquely identify a
connection
> >> : by (ab)using (a few bits of) the new-to-be-assigned portnumber
together
> >> with the Acknowledge-number. But alas, that idea is now outof the
window.
> > > > Is there a specific reason why you insist on implementing TCP/IP with > > such small resources ? > > > > UDP would be much more suitable for such small devices. > > "TCP/IP Lean" by Jeremy Bentham shows how to implement a TCP/IP stack on > a resource limited system. > > Andrew
R.Wieser <address@not.available> wrote:

> David Empson wrote: > > In that situation you aren't allowed to send data in response > > to the ACK of your SYN, because that ACK said the > > window size was zero. > > Nope, it was not Zero. Initially it was about 8 KByte and the redefinition > made it 32 KByte. The packet I did send (after the first ACK) had a > payload of 10 bytes.
In that case, I'm pretty sure you are misinterpreting what is happening, or making a false assumption about how TCP handles acknowledgements. The first ACK from the client confirms the connection is fully established and both ends have agreed on options such as MSS, and established the initial sequence numbers. It is perfectly valid for the server to send data as soon as it gets that ACK (possibly earlier - in the SYN/ACK, depending on what window size the client indicated in its SYN). Each station is supposed to hold "early" data and deliver it to the application after the connection enters the ESTABLISHED state (as per RFC 793). Using Wireshark to look at the packets and the timing would be a big help. I suspect what is happening is something like this: 1. Client sends SYN with initial sequence number and possibly an MSS option. Window size could be zero or 8KB at this point. 2. Server sends SYN/ACK with its initial sequence number and possibly an MSS option. Probably also includes a nonzero window size at this point. 3. Client sends ACK, completing the three-way handshake. Per your comments, the client has indicated a window size of 8KB in this packet. 4.1. Server transmits a packet with 10 bytes of data. 4.2. At the same time (or slightly earlier, at least before the server packet arrives), the client sends another ACK to report a larger window (32KB). 4.3. The server's packet with data arrives at the client. The 10 bytes are delivered to the application. 4.4. The client's ACK with a larger window arrives at the server, not acknowledging any of the data you just sent, because the client hadn't received that packet when it sent its second ack. The second ACK from the client and your data packet crossed in transit. This is perfectly normal. A correctly implemented TCP/IP stack will keep waiting for an acknowledgement which confirms the 10 bytes were received. It is also possible that the client did receive your packet before sending its second ACK, but the client didn't enter the ESTABLISHED state until after your packet arrived. It therefore couldn't deliver the data to the application yet and held onto it briefly. The ACK it sent (upon entering ESTABLISHED and increasing the window size) didn't acknowledge your data, because it hadn't been delivered to the application at that point. 5. A short time later, the client sends another ACK, confirming it has received the 10 bytes you sent. This will probably be after a delay in the order of 200 ms if you haven't sent another packet with further data and the client has no data to send. You would need to hold onto your data for a while and eventually retransmit if that ACK doesn't turn up. Don't forget that TCP is a byte stream protocol. TCP cares little about packets - they are just a means of transporting a sequence of bytes of data, along with piggyback acknowledgements. It is the data bytes which are counted and eventually acknowledged. Apart from special flags like SYN and FIN, you should not be reacting to packets, only to the sequenced data they contain, the updated receive window and the acknowledgement sequence number. You can't expect an instant acknowledgement when you send data. The client's TCP stack will acknowledge your data when it gets around to it, and you may receive one or more packets which don't acknowledge your data, due to delays in the network or other reasons.
> > Don't use the arrival of a specific packet directly as a trigger > > to send. > > That is what I'm trying to evade, but as of now I have no clue to when I'm > allowed to send, as a Server, my first data-packet. :-(
There are three basic cases, if you are observing the packets on the network: (a) If the client gave a nonzero window in its SYN, then you are allowed to send data in the SYN/ACK. (b) If the client gave a zero window in its SYN but a nonzero window in its first ACK, then you are allowed to send data immediately after receiving that ACK. (c) If the client gave a zero window in it SYN and its first ACK but then sends another ACK with a nonzero window, then you are allowed to send data immediately after receiving the second ACK. In all cases, it is the window size reported by the client which determines whether you (as the server) are allowed to send data. You don't need to worry about which packet you have received. You just look at the window size. If you send data "early", it will not be acknowledged by the client until at least the third packet it sends (SYN, ACK and another ACK) and probably not until a later packet, depending on how many packets it sends immediately after the first ACK. Even after you are well into an established connection, any data you send will be acknowledged some time later, and you could receive multiple packets which don't acknowledge the data you sent. You must hold onto your transmit data (or be able to regenerate the same data) until it is acknowledged, and may eventually need to retransmit it after a timeout due to a missing acknowledgement.
> > You might want to look at the open source uIP project to get > > some implementation ideas. It is designed to be used on very > > small systems with limited memory. > > Thanks for the hint. But I'm afraid that a Google-search on a generic > phrase like that will not turn up much (if anything). Do you have an URL ?
You didn't try very hard. :-) Google for "uIP" (without the quotes) and it is the second hit. Google for "uIP TCP/IP" (without the quotes) and it is the first hit. <http://www.sics.se/~adam/uip/index.php/Main_Page> -- David Empson dempson@actrix.gen.nz
On Tue, 05 May 2009 23:40:08 +1200, David Empson wrote:

> It is also possible that the client did receive your packet before > sending its second ACK, but the client didn't enter the ESTABLISHED > state until after your packet arrived. It therefore couldn't deliver the > data to the application yet and held onto it briefly. The ACK it sent > (upon entering ESTABLISHED and increasing the window size) didn't > acknowledge your data, because it hadn't been delivered to the > application at that point.
An OS won't normally delay an ACK until the data is passed up to user-space. Programs won't necessarily read a socket as soon as data is available, and you don't want the peer to keep re-transmitting (and increasing its timeout) just because the client hasn't read the data.
Nobody <nobody@nowhere.com> wrote:

> On Tue, 05 May 2009 23:40:08 +1200, David Empson wrote: > > > It is also possible that the client did receive your packet before > > sending its second ACK, but the client didn't enter the ESTABLISHED > > state until after your packet arrived. It therefore couldn't deliver the > > data to the application yet and held onto it briefly. The ACK it sent > > (upon entering ESTABLISHED and increasing the window size) didn't > > acknowledge your data, because it hadn't been delivered to the > > application at that point. > > An OS won't normally delay an ACK until the data is passed up to > user-space. Programs won't necessarily read a socket as soon as data is > available, and you don't want the peer to keep re-transmitting (and > increasing its timeout) just because the client hasn't read the data.
That seems reasonable. I've also had a closer look at the TCP state diagram and it appears the client should be in the ESTABLISHED state as soon as it sends its first ACK, thus data sent by the server in response to that packet won't need to be held by the client's TCP stack. This means my first theory is more likely: the client's second ACK and the initial data from the server crossed in transit. -- David Empson dempson@actrix.gen.nz
R.Wieser wrote:
> > It looks that an assumption of how things work got the better of me : I > allways thought that the "accept" function would take over the connection > and move it from the origional port to high-numbered one.
Get yourself Richard Stevens' TCP/IP Illustrated series. Reading it will likely save you a lot of trial and much error.
Hello Jan,

> Get yourself Richard Stevens' TCP/IP Illustrated series. > Reading it will likely save you a lot of trial and much error.
I did find and read a few PDFs that show what should be happening. But as they allso did not show the actual data-sending I just assumed it was some info that was just not included. It turned out I was wrong. But I'll see if I can find that book(/books?). Thanks. Regards, Rudy Wieser -- Origional message Jan Brittenson <bson@at_rockgarden.net> schreef in berichtnieuws p5Wdna1xT8YpXp3XnZ2dnUVZ_sOdnZ2d@speakeasy.net...
> R.Wieser wrote: > > > > It looks that an assumption of how things work got the better of me :
I
> > allways thought that the "accept" function would take over the
connection
> > and move it from the origional port to high-numbered one. > > Get yourself Richard Stevens' TCP/IP Illustrated series. Reading it > will likely save you a lot of trial and much error.

The 2024 Embedded Online Conference