In the RL library TCP callback function, the parameters we have are:
soc - Socket number evt - Event (enums defined in Keil's rtl.h) *ptr - Received data frame par - Received data frame length
What I have realised is that the callback parameters don't provide us with any information on TCP packet sequence numbering. Now, my understanding is that TCP packets aren't guaranteed to be received in order, and I also understand that there is no guarantee of a 1:1 relationship between packets transmitted, and those received. This might happen because, for example, the packet hits a network device with a lower MTU resulting in the packet being split; or perhaps two packets are concatenated at some point.
For this reason, my understanding is that TCP must be considered a stream; and that at my application level protocol, I need to implement a means of identifying - at receiving end - that a complete application protocol packet has been fully received. An obvious way of doing this would be to have a header in my application packet that contains a packet length. At the receive end, I would keep reading data in TCP_EVT_DATA of the callback and rebuild the application packet locally until I have the required message size. I would still have to do this even if I guaranteed that my packets were 'small' enough to fit into a single TCP packet at transmit end, because as stated above it's a stream; there's no way to guarantee a single packet out for every packet shoved in (even though, most of the time, it probably is 1:1).
A further requirement, in order to be very robust, is to also look at the TCP packet sequence numbering to ensure that the application packet is rebuilt without any parts in the wrong order. But as the RL-Library callback doesn't provide this, do I just have to assume that it's unlikely that TCP will not deliver packets in order? To protect against that happening, would I be best using a CRC check on my entire reassembled packet?
Or, does the Keil libary already just deal with this for me, and guarantee packets delivered to the callback in order? I'd have thought that's most unlikely, considering the resource limitations.
Any thoughts are appreciated - even if it's to tell me I'm barking up the wrong tree.
Regards
Trev
From the application's point of view it is quite simple.
The sender sends a stream and the receiver receives the stream. The receiver receives it in the same order as was transmitted.
The TCP protocol stack looks after the sequence/acknowledgement numbers, retransmissions, ensuring correct packet order etc.
One thing that you must bear in mind is that you should not rely on a block being received with the same size as that sent. TCP is stream oriented, not block oriented. So if you want to communicate blocks, the stream must contain something that allows the receiver to re-construct a transmitted block. A typical approach would be to send the block length followed by the block data.
"...do I just have to assume that it's unlikely that TCP will not deliver packets in order?"
If the protocol stack works correctly (and RL-ARM has never done anything to make me think different), then out of order packets should never be received.
"To protect against that happening, would I be best using a CRC check on my entire reassembled packet?
TCP packets have a checksum covering each packet communicated. If you go over Ethernet, then there is a CRC. Other mediums might include other checks. You might want to include a CRC over the data if you want extra confidence.
Thank you for your response, IB. It's much appreciated. (The forum seemed to have been a bit broken yesterday, so I wasn't really expecting any response - or for anyone to even see my post :-) )
I entirely agree about the protocol being stream oriented; for this reason I've already decided to implement a header complete with a length field, as briefly mentioned before.
I'm aware that the IP layer has some CRC checking, and at TCP level there is some limited 16-bit integrity checking. The purpose of applying my own CRC to the overall recovered application protocol packet is in case of unordered packets. However, as you say, hopefully the Keil stack guarantees correct order of packets in the callback anyway; perhaps the memory pool is used to cache any packet while a 'skipped' one is awaited.
"... hopefully the Keil stack guarantees correct order of packets in the callback anyway ..."
I don't think you should include the word hopefully. The TCP stack is expected to carry out this function - If a situation were found where it doesn't do this, then it would simply be referred to as a bug.
I've been working with the TCPnet for quite a while now and, although I've seen a few faults, I've never seen any 'out of order' TCP data.