tcp_write function merges 2 different packets while sending

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

tcp_write function merges 2 different packets while sending

Urvi
Hi Everyone,

I am using lwIP stack for my application where my device acts as a client.
During communication with the server, device sends data packets using
tcp_write() and then calls tcp_output() function to send data immediately.

But when I send 1 data packet of size=6 bytes (call tcp_write() and then
tcp_output()) and next packet of size=45 bytes (call tcp_write() and then
tcp_output()), then at server side it receives as a one single data packet
of size=51 bytes; due to this my complete data packet becomes garbage and I
got failure in communication. (this is just one packet example, but it
happens often).


How to solve this issue?





--
Sent from: http://lwip.100.n7.nabble.com/lwip-users-f3.html

_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: tcp_write function merges 2 different packets while sending

goldsimon@gmx.de


Urvi wrote:

>[..]
>
>But when I send 1 data packet of size=6 bytes (call tcp_write() and
>then
>tcp_output()) and next packet of size=45 bytes (call tcp_write() and
>then
>tcp_output()), then at server side it receives as a one single data
>packet
>of size=51 bytes; due to this my complete data packet becomes garbage
>and I
>got failure in communication. (this is just one packet example, but it
>happens often).
>
>
>How to solve this issue?

That's expected TCP behaviour, not an lwIP issue. Of you need datagrams strictly separated, use UDP.

Regards,
Simon

_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: tcp_write function merges 2 different packets while sending

Rod Boyce-2

On 21/12/2019 08:53, goldsimon wrote:

>
> Urvi wrote:
>> [..]
>>
>> But when I send 1 data packet of size=6 bytes (call tcp_write() and
>> then
>> tcp_output()) and next packet of size=45 bytes (call tcp_write() and
>> then
>> tcp_output()), then at server side it receives as a one single data
>> packet
>> of size=51 bytes; due to this my complete data packet becomes garbage
>> and I
>> got failure in communication. (this is just one packet example, but it
>> happens often).
>>
>>
>> How to solve this issue?
> That's expected TCP behaviour, not an lwIP issue. Of you need datagrams strictly separated, use UDP.
>
> Regards,
> Simon
>
> _______________________________________________
> lwip-users mailing list
> [hidden email]
> https://lists.nongnu.org/mailman/listinfo/lwip-users


TCP is a streaming protocol this means that packets can be joined
together either at the sender or the receiver.

UDP will keep the packets separate but sending a 6 byte packet is very
inefficient over Ethernet. 

The minimum Ethernet packet size is 64-bytes, if you are the protocol
owner I would suggest some sort of packet ageration to merge smaller
packets and make for a more efficient transfer over Ethernet.


Rod



_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: tcp_write function merges 2 different packets while sending

Trampas Stern
A simple protocol I often use is a header/data system like: 


//header
uint8_t flag;  //number  that is start of packet
uint8_t version; //protocol version number or type of packet
uint32_t bytes;  //number of bytes in data packet
uint32_t  headerCRC;  //CRC of the header


//Data packet
uint8_t data[];
uint32_t dataCRC; 

A Packet is a header followed by a the data
 
This allows me to scan for the flag and then check for valid header using CRC if found then I parse data. If header is not valid I scan for flag until I find a valid header.  

Depending on what you need you can adjust the number of bits per field as needed.  I usually leave the CRC as last field in header/data such that the CRC can be calculated as data is sent (while streaming). 

The version number is important, too often people change protocol versions (use checksum, or use different field bit sizes) by having version you can support multiple versions as needed, so always include a version number.  Sometimes if I am tight on space I will skip the flag byte and then just check every byte for valid header.  This all depends on what you need.... 

I have seen people try to optimize packet sizes, for example in the above if you need to send 4 bytes of data the over head is huge relative speaking. However in my experience every time someone has "optimized" their protocol they end up regretting it, especially if they did not include a version number. 

With TCP/IP however the data is guaranteed to be delivered with no errors.  Thus even sending ASCII strings where the NULL char is the separator will work just fine.  Thus for TCP/IP I often stick with ASIC and JSON as it is easy to parse and debug. 



On Sat, Dec 21, 2019 at 11:41 AM Rod Boyce <[hidden email]> wrote:

On 21/12/2019 08:53, goldsimon wrote:
>
> Urvi wrote:
>> [..]
>>
>> But when I send 1 data packet of size=6 bytes (call tcp_write() and
>> then
>> tcp_output()) and next packet of size=45 bytes (call tcp_write() and
>> then
>> tcp_output()), then at server side it receives as a one single data
>> packet
>> of size=51 bytes; due to this my complete data packet becomes garbage
>> and I
>> got failure in communication. (this is just one packet example, but it
>> happens often).
>>
>>
>> How to solve this issue?
> That's expected TCP behaviour, not an lwIP issue. Of you need datagrams strictly separated, use UDP.
>
> Regards,
> Simon
>
> _______________________________________________
> lwip-users mailing list
> [hidden email]
> https://lists.nongnu.org/mailman/listinfo/lwip-users


TCP is a streaming protocol this means that packets can be joined
together either at the sender or the receiver.

UDP will keep the packets separate but sending a 6 byte packet is very
inefficient over Ethernet. 

The minimum Ethernet packet size is 64-bytes, if you are the protocol
owner I would suggest some sort of packet ageration to merge smaller
packets and make for a more efficient transfer over Ethernet.


Rod



_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users

_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: tcp_write function merges 2 different packets while sending

Rod Boyce-2

Sir,


The packet definition is fine for normal generic multi-transport use.

if you want to use TCP then on the receive side you want to read packet in either of the 2 ways below:

1. Just read to parse a header number of bytes, if packet valid read the number of data bytes + CRC, then process packet.

Or

2. Read as much data as is available then search buffer for header & packet, save any leftover data.  process packet.  Then parse remainder of data, if another packet found process packet.  If there is any leftover data once all packets have finished append new received data to end of left over data and start again.

The 2nd option is more complicated but does not rely on data being stored in kernel buffers or network retries.

This is commonly called a packet catcher.

Regards,

Rod


On 21/12/2019 18:23, Trampas Stern wrote:
A simple protocol I often use is a header/data system like: 


//header
uint8_t flag;  //number  that is start of packet
uint8_t version; //protocol version number or type of packet
uint32_t bytes;  //number of bytes in data packet
uint32_t  headerCRC;  //CRC of the header


//Data packet
uint8_t data[];
uint32_t dataCRC; 

A Packet is a header followed by a the data
 
This allows me to scan for the flag and then check for valid header using CRC if found then I parse data. If header is not valid I scan for flag until I find a valid header.  

Depending on what you need you can adjust the number of bits per field as needed.  I usually leave the CRC as last field in header/data such that the CRC can be calculated as data is sent (while streaming). 

The version number is important, too often people change protocol versions (use checksum, or use different field bit sizes) by having version you can support multiple versions as needed, so always include a version number.  Sometimes if I am tight on space I will skip the flag byte and then just check every byte for valid header.  This all depends on what you need.... 

I have seen people try to optimize packet sizes, for example in the above if you need to send 4 bytes of data the over head is huge relative speaking. However in my experience every time someone has "optimized" their protocol they end up regretting it, especially if they did not include a version number. 

With TCP/IP however the data is guaranteed to be delivered with no errors.  Thus even sending ASCII strings where the NULL char is the separator will work just fine.  Thus for TCP/IP I often stick with ASIC and JSON as it is easy to parse and debug. 



On Sat, Dec 21, 2019 at 11:41 AM Rod Boyce <[hidden email]> wrote:

On 21/12/2019 08:53, goldsimon wrote:
>
> Urvi wrote:
>> [..]
>>
>> But when I send 1 data packet of size=6 bytes (call tcp_write() and
>> then
>> tcp_output()) and next packet of size=45 bytes (call tcp_write() and
>> then
>> tcp_output()), then at server side it receives as a one single data
>> packet
>> of size=51 bytes; due to this my complete data packet becomes garbage
>> and I
>> got failure in communication. (this is just one packet example, but it
>> happens often).
>>
>>
>> How to solve this issue?
> That's expected TCP behaviour, not an lwIP issue. Of you need datagrams strictly separated, use UDP.
>
> Regards,
> Simon
>
> _______________________________________________
> lwip-users mailing list
> [hidden email]
> https://lists.nongnu.org/mailman/listinfo/lwip-users


TCP is a streaming protocol this means that packets can be joined
together either at the sender or the receiver.

UDP will keep the packets separate but sending a 6 byte packet is very
inefficient over Ethernet. 

The minimum Ethernet packet size is 64-bytes, if you are the protocol
owner I would suggest some sort of packet ageration to merge smaller
packets and make for a more efficient transfer over Ethernet.


Rod



_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users

_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users

_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: tcp_write function merges 2 different packets while sending

Urvi
In reply to this post by goldsimon@gmx.de
Thank you Everyone for your reply.

First of all I am using TLS/SSL handshaking over lwIP for my IoT
application. So I can't opt for UDP instaed of TCP.
Second thing is that all data packets of any size (i.e. 6/45/51/384/854
bytes) are generated by TLS library at the time of handshaking. So I don't
have any control on data packet framing as it is done by tls library.

So in this case how am I able to overcome this problem?




--
Sent from: http://lwip.100.n7.nabble.com/lwip-users-f3.html

_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: tcp_write function merges 2 different packets while sending

Ajay Bhargav (SiWi)
In reply to this post by Urvi

TCP will tend to merge that’s expected behaviour. You need to check your server side application. SSL usually reads the expected number of bytes while handshaking/doing any kind of transaction. So even if packets are merged server side will read bytes in expected order.

 

-Ajay

 

 

From: [hidden email]
Sent: Monday, December 23, 2019 2:39 PM
To: [hidden email]
Subject: Re: [lwip-users] tcp_write function merges 2 different packets while sending

 

Thank you Everyone for your reply.

 

First of all I am using TLS/SSL handshaking over lwIP for my IoT

application. So I can't opt for UDP instaed of TCP.

Second thing is that all data packets of any size (i.e. 6/45/51/384/854

bytes) are generated by TLS library at the time of handshaking. So I don't

have any control on data packet framing as it is done by tls library.

 

So in this case how am I able to overcome this problem?

 

 

 

 

--

Sent from: http://lwip.100.n7.nabble.com/lwip-users-f3.html

 

_______________________________________________

lwip-users mailing list

[hidden email]

https://lists.nongnu.org/mailman/listinfo/lwip-users

 


_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: tcp_write function merges 2 different packets while sending

Liju John
Still you can disable the streaming feature of the TCP and send like udp packets with TCP_NODELAY set socket option on the TCP level. This option is available on the socket. You can explore on it.

--Liju.

On Mon, Dec 23, 2019 at 2:57 PM Ajay Bhargav <[hidden email]> wrote:

TCP will tend to merge that’s expected behaviour. You need to check your server side application. SSL usually reads the expected number of bytes while handshaking/doing any kind of transaction. So even if packets are merged server side will read bytes in expected order.

 

-Ajay

 

 

From: [hidden email]
Sent: Monday, December 23, 2019 2:39 PM
To: [hidden email]
Subject: Re: [lwip-users] tcp_write function merges 2 different packets while sending

 

Thank you Everyone for your reply.

 

First of all I am using TLS/SSL handshaking over lwIP for my IoT

application. So I can't opt for UDP instaed of TCP.

Second thing is that all data packets of any size (i.e. 6/45/51/384/854

bytes) are generated by TLS library at the time of handshaking. So I don't

have any control on data packet framing as it is done by tls library.

 

So in this case how am I able to overcome this problem?

 

 

 

 

--

Sent from: http://lwip.100.n7.nabble.com/lwip-users-f3.html

 

_______________________________________________

lwip-users mailing list

[hidden email]

https://lists.nongnu.org/mailman/listinfo/lwip-users

 

_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users

_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: tcp_write function merges 2 different packets while sending

goldsimon@gmx.de


Liju John wrote:
>Still you can disable the streaming feature of the TCP and send like
>udp
>packets with TCP_NODELAY set socket option on the TCP level. This
>option is
>available on the socket. You can explore on it.

While this is correct, it's not a good suggestion in this thread: the remote host is free to combine multiple rx packets into one 'read' call, so even if tx is framed as written, it may or may not work on the remote side.

An I say it's even dangerous to rely on this as it might work until segments are dropped. You think the system is working, but in fact, it might break on first packet loss.

Instead, so the right think and create your application layer protocol so that it can handle a byte stream, not rely on packets.

Regards,
Simon

_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users