目录
(三)数据包输入到本机:ip_local_delivery ()
(四)向高层协议分发:ip_local_deliver_finish ()
一、什么是 IPv4 数据包
在深入探讨 IPv4 数据包的接收实现之前,我们先来了解一下什么是 IPv4 数据包。IP,即互联网协议(Internet Protocol) ,是 TCP/IP 协议族的核心,负责在网络中实现终端节点之间的通信,也被称为 “点对点通信” 。而 IPv4,作为 IP 协议的第四个版本,也是目前广泛使用的版本,它通过 32 位的地址为互联网上的每个网络和主机分配一个唯一的逻辑地址,以此确保数据能够在复杂的网络环境中准确传输。
IPv4 数据包,作为 IPv4 协议中数据传输的基本单位,就像是网络世界里的 “包裹”,里面装着我们需要传输的数据。这个 “包裹” 由两部分组成:首部和数据部分。首部包含了关于该数据包的路由和控制信息,就好比是包裹上的快递单,写明了寄件人(源 IP 地址)、收件人(目的 IP 地址)、快递的有效期(生存时间 TTL)等关键信息,这些信息指导着数据包在网络中的传输路径和处理方式;数据部分则是真正要传输的内容,比如我们上网时发送的文本消息、图片、视频等,它们可以是上层协议(如 TCP、UDP)的数据段 。简单来说,IPv4 数据包在网络传输中扮演着至关重要的角色,它是实现网络通信的基础,承载着我们在互联网上的各种数据交互。
二、IPv4 数据包的结构探秘
了解了 IPv4 数据包的概念后,下面让我们深入剖析一下 IPv4 数据包的结构。IPv4 数据包由首部和数据两部分构成,其中首部包含了众多重要字段,这些字段携带了关于数据包的各种关键信息,它们协同工作,确保数据包能够在网络中准确、高效地传输 。
IPv4 数据包首部的前 20 个字节是固定长度,包含了一些基本的、必不可少的字段;在这之后,是长度可变的可选字段,最长可达 40 字节,用于满足一些特殊的需求 。下面我们来详细介绍 IPv4 数据包首部的各个字段:
-
版本(Version):占 4 位,用于标识 IP 协议的版本号。对于 IPv4,该字段的值固定为 4,它就像是数据包的 “身份标签”,明确告诉网络设备这个数据包遵循的是 IPv4 协议,接收方设备会根据这个版本信息来正确地解析和处理数据包 。如果发送方和接收方使用的 IP 协议版本不一致,就可能导致通信失败,就好比两个人说不同的语言,无法进行有效的交流。
-
首部长度(Header Length):同样占 4 位,它表示的是整个 IP 包头的长度,单位是 4 字节。该字段的取值范围是 0000 - 1111(十进制数 0 - 15) ,这意味着 IP 包头的最小长度为 0 字节(实际中几乎不会出现),最大长度为 60 字节(15 * 4 = 60)。一般情况下,当没有使用任何可选字段时,首部长度的值为 0101(十进制的 5),表示头长度为 20 字节,这也是最常见的情况。首部长度字段就像是一个 “尺子”,让接收方知道从哪里开始读取数据包的数据部分 。
-
服务类型(Type of Service,ToS):占 8 位,这个字段也被称为差分服务代码点(Differentiated Services Code Point,DSCP) ,用于指定数据包的优先级和所期望的服务质量(Quality of Service,QoS) 。它的前 3 位表示优先级,取值越大,数据就越重要,例如,实时语音和视频流数据可能会被赋予较高的优先级,以确保它们能够及时、流畅地传输,避免出现卡顿;后 5 位分别表示不同的服务类型偏好,如低延迟(D,Delay)、高吞吐量(T,Throughput)、高可靠性(R,Reliability)和低传输成本(M, Monetary cost)等 。不过在实际应用中,这个字段并没有得到广泛的使用 。
-
总长度(Total Length):占 16 位,它指示的是整个 IP 数据包(包括首部和数据部分)的长度,单位是 1 字节 。由于该字段是 16 位,所以 IP 数据包的最大长度理论上可以达到 2^16 - 1 = 65535 字节 。但在实际的网络传输中,受到链路层最大传输单元(MTU,Maximum Transmission Unit)的限制,例如,以太网的 MTU 通常为 1500 字节,当 IP 数据包的总长度超过链路层的 MTU 时,数据包就需要进行分片处理,将大的数据包分割成多个较小的片段,每个片段都有自己的首部,这些片段在到达目的地后再重新组装成完整的数据包 。
-
标识符(Identification):长度为 16 位,当 IP 对上层数据进行分片时,它会给所有的分片分配一组编号,然后将这些编号放入标识符字段中 。简单来说,它就像是一个 “分组标签”,属于同一个原始数据包的所有分片都具有相同的标识符,这样接收方就可以根据这个标识符来识别哪些分片属于同一个原始数据包,从而正确地将它们重组 。例如,当你邮寄一个大包裹时,如果包裹太大,快递公司可能会将其分成几个小包裹进行邮寄,每个小包裹上都会贴上相同的编号标签,以便收件人能够识别这些小包裹是来自同一个大包裹,最后将它们组合在一起 。
-
标志(Flags):占 3 位,目前只有后两位有效,分别是 DF(Don't Fragment)和 MF(More Fragments) 。DF 位表示是否允许分片,当 DF 位设为 1 时,表明路由器不能对该上层数据包分段,如果一个上层数据包无法在不分段的情况下进行转发,那么路由器会丢弃该上层数据包并返回一个错误信息;MF 位表示后面是否还有分片,当 MF 位为 1 时,表示后面还有分片,当 MF 位为 0 时,则表示这是最后一个分片 。
-
片偏移(Fragment Offset):占 13 位,它指明了每个分片相对于原始报文开头的偏移量,单位是 8 字节 。也就是说,接收方可以根据片偏移字段的值,确定每个分片在原始数据包中的位置,从而将各个分片按照正确的顺序进行组装 。比如,一个长度为 2000 字节的 IP 报文(其中 20 字节为包头,1980 字节为数据),到达路由器时,由于超过了链路层的 MTU(假设为 1500 字节),需要进行分片 。那么第一个分片的数据部分长度为 1480 字节(1500 - 20),片偏移就是 0,表示该分片在 1980 字节数据的第 0 位开始,第 1479 位结束;第二个分片的数据部分长度为 500 字节(1980 - 1480),片偏移为 185(1480 / 8),表示该分片开始的位置在原来 IP 数据的第 1480 位,结束在 2000 位 。
-
生存时间(Time to Live,TTL):占 8 位,最初设计时是以秒为单位记录当前包在网络上应该生存的期限,但在实际应用中,它指的是数据包可以中转多少个路由器的意思 。每经过一个路由器,TTL 的值就会减少 1,当 TTL 减少为 0 时,该数据包就会被丢弃 。这个字段的存在是为了防止数据包在网络中由于路由环路等原因而被无休止地转发,浪费网络带