tcp、udp、分包粘包

MTU

UDP和TCP报头使用两个字节存放端口号,所以端口号的有效范围是从0到65535。动态端口的范围是从1024到65535。每个以太网帧都有最小的大小64Bytes最大不能超过1518Bytes,对于小于或者大于这个限制的以太网帧我们都可以视之为错误的数据帧,一般的以太网转发设备会丢弃这些数据帧。 

 由于以太网EthernetII最大的数据帧是1518Bytes这样,刨去以太网帧的帧头(DMAC目的MAC地址48bits=6Bytes+SMAC源MAC地址48bits=6Bytes+Type域2Bytes)14Bytes和帧尾CRC校验部分4Bytes那么剩下承载上层协议的地方也就是Data域最大就只能有1500Bytes这个值我们就把它称之为MTU

UDP 包的大小就应该是 1500 - IP头(20) - UDP头(8) = 1472(Bytes)

TCP 包的大小就应该是 1500 - IP头(20) - TCP头(20) = 1460 (Bytes)

分包与否

如果我们定义的TCP和UDP包没有超过范围,那么我们的包在IP层就不用分包了,这样传输过程中就避免了在IP层组包发生的错误;如果超过范围,既IP数据报大于1500字节,发送方IP层就需要将数据包分成若干片,而接收方IP层就需要进行数据报的重组。更严重的是,如果使用UDP协议,当IP层组包发生错误,那么包就会被丢弃。接收方无法重组数据报,将导致丢弃整个IP数据报。UDP不保证可靠传输;但是TCP发生组包错误时,该包会被重传,保证可靠传输。在IP层(网络层)分包组包。

tcp、udp、分包粘包_第1张图片

粘包与否

TCP常常被称作一种“流协议”,会进行拥塞/流量控制。发送端为了将多个发往(send,write)接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包,再发往接收端(recv,read),所以一定处理粘包问题,其一方案是有效负载中加入length数据。

UDP不存在粘包问题,是由于UDP发送的时候,没有经过Negal算法优化,不会将多个小包合并一次发送出去。另外,在UDP协议的接收端,采用了链式结构来记录每一个到达的UDP包,这样接收端应用程序一次recv只能从socket接收缓冲区中读出一个数据包。也就是说,发送端send(write)了几次,接收端必须recv(read)几次(无论recv时指定了多大的缓冲区)。

Internet(非局域网)上的标准MTU值为576字节,所以建议在进行Internet的UDP编程时,最好将UDP的数据长度控制在548字节 (576-8-20)以内。

当发送的有效数据大于1472字节时,也就是说IP数据报大于1500字节,大于MTU,这个时候发送方IP层就需要分片(fragmentation)。把数据报分成若干片,使每一片都小于MTU.而接收方IP层则需要进行数据报的重。这样就会多做许多事情,而更严重的是,由于UDP的特性,当某一片数据传送中丢失时,接收方便无法重组数据报.将导致丢弃整个UDP数据报。此时所以我们自己分包(片),组包(片)。

TCP、UDP数据包最小值的确定

根据第一幅图,发送的udp有效数据最好超过46-IP头(20) - UDP头(8) = 18字节,发送的tcp有效数据最好超过46-IP头(20) - TCP头(20) = 6字节,否则可能会出现接收不到的情况。


参考:

https://blog.csdn.net/caoshangpa/article/details/51530685      

https://blog.csdn.net/hik_zxw/article/details/48398935

你可能感兴趣的:(网络,tcpip,udp,粘包)