还记得四层网络协议长什么样子吗?
四层网络协议
为什么要将数据切片
软件琛琛是属于应用层上的。
而"李东","亚健康终结者"这两条消息在进入传输层时使用的是传输层上的 TCP 协议。消息在进入传输层(TCP)时会被切片为一个个数据包。这个数据包的长度是MSS
。
可以把网络比喻为一个水管,是有一定的粗细的,这个粗细由网络接口层(数据链路层)提供给网络层,一般认为是的MTU
(1500),直接传入整个消息,会超过水管的最大承受范围,那么,就需要进行切片,成为一个个数据包,这样消息才能正常通过“水管”。
上面说的其实就是TCP
的 Nagle 算法优化,目的是为了避免发送小的数据包。
在 Nagle 算法开启的状态下,数据包在以下两个情况会被发送:
- 如果包长度达到
MSS
(或含有Fin
包),立刻发送,否则等待下一个包到来;如果下一包到来后两个包的总长度超过MSS
的话,就会进行拆分发送; - 等待超时(一般为
200ms
),第一个包没到MSS
长度,但是又迟迟等不到第二个包的到来,则立即发送。
TCP数据长度
跟 UDP 不同在于,TCP 发送端在发的时候就不保证发的是一个完整的数据报,仅仅看成一连串无结构的字节流,这串字节流在接收端收到时哪怕知道长度也没用,因为它很可能只是某个完整消息的一部分。
为什么长度字段冗余还要加到 UDP 首部中
关于这一点,查了很多资料,《 TCP-IP 详解(卷2)》
里说可能是因为要用于计算校验和。也有的说是因为UDP底层使用的可以不是IP协议,毕竟 IP 头里带了总长度,正好可以用于计算 UDP 数据的长度,万一 UDP 的底层不是IP层协议,而是其他网络层协议,就不能继续这么计算了。
但我觉得,最重要的原因是,IP 层是网络层的,而 UDP 是传输层的,到了传输层,数据包就已经不存在IP头信息了,那么此时的UDP数据会被放在 UDP 的 Socket Buffer
中。当应用层来不及取这个 UDP 数据报,那么两个数据报在数据层面其实都是一堆 01 串。此时读取第一个数据报的时候,会先读取到 UDP 头部,如果这时候 UDP 头不含 UDP 长度信息,那么应用层应该取多少数据才算完整的一个数据报呢?
因此 UDP 头的这个长度其实跟 TCP 为了防止粘包而在消息体里加入的边界信息是起一样的作用的。