IP报文结构
- 4位版本号: 指定IP协议的版本, 对于IPv4来说, 就是4.
- 4位头部长度: IP头部的长度是多少个32bit, 也就是 length * 4 的字节数. 4bit表示最大的数字是15, 因此IP头部最大长度是60字节.
- 8位服务类型: 3位优先权字段(已经弃用) + 4位TOS字段 + 1位保留字段(必须置为0). 4位TOS分别表示: 最小延时, 最大吞吐量, 最高可靠性, 最小成本.。这四者相互冲突, 只能选择一个。 对ssh/telnet这样的应用程序,最小延时比较重要;对于ftp这样的程序, 最大吞吐量比较重要.
- 16位总长度: IP数据报整体占多少个字节.
- 16位标识: 唯一的标识主机发送的报文. 如果IP报文在数据链路层被分片了, 那么每一个片里面的这个id都是相同的.
- 3位标志字段: 第一位保留(保留的意思是现在不用, 但是还没想好说不定以后要用到). 第二位置为1表示禁止分片, 这时候如果报文长度超过MTU, IP模块就会丢弃报文. 第三位表示"更多分片", 如果分片了的话, 最后一个分片置为0, 其他是1. 类似于一个结束标记.
- 13位分片偏移: 是分片相对于原始IP报文开始处的偏移. 其实就是在表示当前分片在原报文中处在哪个位置. 实际偏移的字节数是这个值 * 8 得到的. 因此, 除了最后一个报文之外, 其他报文的长度必须是8的整数倍(否则报文就不连续了).
- 8位生存时间(TTL): 数据报到达目的地的最大报文跳数. 一般是64. 每次经过一个路由, TTL -= 1, 一直减到0还没到达, 那么就丢弃了. 这个字段主要是用来防止出现路由循环 。
- 8位协议: 表示上层协议的类型
- 16位头部校验和: 使用CRC进行校验, 来鉴别头部是否损坏.
- 32位源地址和32位目标地址: 表示发送端和接收端.
- 选项字段(不定长, 最多40字节)
IP如何区分有效载荷和报头
IP数据包中的报头和有效载荷主要可以通过以下两点进行区分:
- 报头长度字段
IP头部有一个4位的"报头长度"字段,单位为4字节,它指明了当前报头包含的4字节段数量。
所以根据这个长度值就可以确定报头部分的字节数。
例如,如果报头长度值为5,则报头的大小是 5 * 4 = 20字节。
- 报头固定格式
IP报头有固定的格式,共包含了10个标准字段,加上可选字段,最大长度为60字节。这些字段包含版本号、服务类型、总长度等信息。
每个字段的位置和长度是固定的。所以可以通过格式解析出报头的具体内容。
有效载荷部分则没有固定格式,它存放的是上层协议(TCP/UDP等)的报文。
为什么需要4位首部长度
IP报头的最小长度确实是20字节。之所以还需要在报头中指定长度,主要有以下两个原因:
- IP报头长度可变
虽然最小长度是20字节,但IP头部中的可选字段使得其长度可以变化,最大可达60字节。这就需要长度字段来动态指示当前报头的实际长度。
- 方便解析报文
在数据链路层,IP数据报会加上各种头部,形成帧。接收方需要先解析这些头部,才能获得IP报头的位置。如果每次都默认IP头部是20字节,解析就会非常不灵活。
所以,尽管最小长度固定是20字节,IP头部中还是有必要包含一个 LENGTH 字段,来动态指示当前报头的长度,这对解析报文和扩展协议都非常重要。