TCP/IP 协议栈
IP 数据报格式
首部的格式
- 版本( version )
- IPV4/IPV6
- 首部长度
- 单位是 4B ,最小为 5
- 区分服务
- 指示期望获得哪种类型服务(数据报的优先级等等)
- 总长度
- 首部+数据,单位 1B
- 生存时间
- IP 分组的保质期,经过一个路由器-1,变成0则丢弃(防止数据报在网络兜圈子)
- 协议
- 数据部分的协议
- 如下:
协议名 | ICMP | IGMP | TCP | EGP | IGP | UDP | IPV6 | ESP | OSPF |
---|---|---|---|---|---|---|---|---|---|
字节 | 1 | 2 | 6 | 8 | 9 | 17 | 41 | 50 | 89 |
- 首部检验和
- 只检验首部,在检验首部用的方法
- 源地址
- 32 位
- 目的地址
- 32 位
- 可选字段
- 0~40B,用来支持排错,测量及安全等措施。
- 填充
- 全 0 ,把首部补成 4B 的整数倍。
IP 数据报分片
最大传送单元 MTU
链路层数据帧可封装数据的上限
以太网的 MTU 是 1500 字节
上面是一个 IP分组,也叫 IP数据报,它分为首部和数据部分,然后经过封装,形成链路层的数据帧,封装就是加头加尾。然后 IP 分组就成了数据帧的数据部分,那么这个数据部分就有最大要求值(MTU)
如果传送的数据超过了这个 MTU 值,怎么办?
解决方法就是 分片,当然,要看分组是否也许,如果分组不也许,那么将不能在往下传,返回一个差错报文。
那么分片怎么理解,这要结合 IP 数据报的格式中的“标识”,“标志”,“片偏移”
字段解释
- 标识
- 同一数据报的分片,使用同一标识。
- 标志
- 一共又三位,只有中间那位和最低位有意义 x _ _
- 中间为 DF (Don’t Fragment)
- DF = 1 , 禁止分片
- DF = 0 ,也许分片
- 最低位 MF (More Fragment)
- MF = 1,后面“还有分片”
- MF = 0,代表最后一片/没分片
- 片偏移
- 指出较长的分组分片后,某片在原分组中的相对位置,以 8B 字节为单位。
- 我们知道,片偏移是 13 位,如果它数值是 0…1 ,代表十进制 1,那么它的位置在原来分组或者数据报的相对位置,1 * 8B = 8B ,也就是在原来位置的第 8B 字节开始的位置
- 出了最后一个分片,每个分片的长度一定是 8B 的整数倍
- 指出较长的分组分片后,某片在原分组中的相对位置,以 8B 字节为单位。
例题
如图,这里 MTU 是 1420B,数据部分和首部加起来 3820B ,超过了最大,需要分片。
其中 20B 是要作为首部的,剩下的 1400B 才能作为数据部分。分片之后,如图:
那么每个数据报片的片偏移是多少?
首先我们规定刚开始还没被分的数据部分,第一个字节成为 0 字节,依次类推。
第一数据报片,它拿出来 1400B ,从 0B~1399B 被取出,那么它的偏移量是多少?也就是距离原来的数据报的最开始的位置有多远。其实是 0 ,因为它从 0B 开始拿,相对于原来数据报开始位置没有距离的。
第二数据分片,它从 1400B~2799B,最后的部分是原来数据部分的 2799B,那么偏移量多少?我们,假设放回去,从 1400B 开始,距离开始位置 1400B,然后 除以 8,1400/8=175,那么它的片偏移量为 175。那么首部字段片偏移为 175。
第三数据分片,它的数据部分只剩 1000B,它从 2800B~3799B,最后的部分是原来数据部分的 3799B,那么偏移量多少? 我们假设放回去,从 2800B 开始,距离开始位置 2800B,用这个分片的第一个启示字节也就是 2800B,然后除以 8,2800/8=350,那么它的片偏移量为 350。那么首部字段片偏移为 350。
最后总结如下图:
temp | 总长度 | 标识 | MF | DF | 片偏移 |
---|---|---|---|---|---|
原始数据报 | 3820 | 12345 | 0 | 0 | 0 |
数据报片1 | 1420 | 12345 | 1 | 0 | 0 |
数据报片2 | 1420 | 12345 | 1 | 0 | 175 |
数据报片3 | 1020 | 12345 | 0 | 0 | 350 |
注意:
这里的每个数据报片都要随原来的包含首部,数据部分根据 MTU 分片。最后一个剩多少就是多少。
总结
对应IP数据报的格式中,首部长度,总长度,片偏移
- 总长度单位 1B
- 片偏移单位是 8B
- 首部长度单位是 4B
这里单位是什么意思?用总长度来说,也就是总长度是 16 位,它的字段值为 0…1 ,前面 15 个0,后面 1个1,然后用总长度字段的值乘以 1B ,1x1B=1B,总长度就是 1B(当然这里只是假设,总长度不会那么小)