我把自己以往的文章汇总成为了 Github ,欢迎各位大佬 star
https://github.com/crisxuan/bestJavaer
IP 协议
路由器对分组进行转发后,就会把数据包传到网络上,数据包最终是要传递到客户端或者服务器上的,那么数据包怎么知道要发往哪里呢?起到关键作用的就是 IP 协议。
IP 主要分为三个部分,分别是 IP 寻址、路由和分包组包 。下面我们主要围绕这三点进行阐述。
IP 地址
既然一个数据包要在网络上传输,那么肯定需要知道这个数据包到底发往哪里,也就是说需要一个目标地址信息, IP 地址就是连接网络中的所有主机进行通信的目标地址 ,因此,在网络上的每个主机都需要有自己的 IP 地址。
在 IP 数据报发送的链路中,有可能链路非常长,比如说由中国发往美国的一个数据报,由于网络抖动等一些意外因素可能会导致数据报丢失,这时我们在这条链路中会放入一些 中转站
,一方面能够确保数据报是否丢失,另一方面能够控制数据报的转发,这个中转站就是我们前面聊过的路由器,这个转发过程就是 路由控制
。
路由控制(Routing)
是指将分组数据发送到最终目标地址的功能,即时网络复杂多变,也能够通过路由控制到达目标地址。因此,一个数据报能否到达目标主机,关键就在于路由器的控制。
这里有一个名词,就是 跳
,因为在一条链路中可能会布满很多路由器,路由器和路由器之间的数据报传送就是跳,比如你和隔壁老王通信,中间就可能会经过路由器 A-> 路由器 B -> 路由器 C 。
那么一跳的范围有多大呢?
一跳是指从源 MAC 地址到目标 MAC 地址之间传输帧的区间 ,这里引出一个新的名词,MAC 地址是啥?
MAC 地址指的就是计算机的物理地址(Physical Address)
,它是用来确认网络设备位置的地址。在 OSI 网络模型中,网络层负责 IP 地址的定位,而数据链路层负责 MAC 地址的定位。MAC 地址用于在网络中唯一标示一个网卡,一台设备若有一或多个网卡,则每个网卡都需要并会有一个唯一的 MAC 地址,也就是说 MAC 地址和网卡是紧密联系在一起的。
路由器的每一跳都需要询问当前中转的路由器,下一跳应该跳到哪里,从而跳转到目标地址。而不是数据报刚开始发送后,网络中所有的通路都会显示出来,这种多次跳转也叫做多跳路由
。
IP 地址定义
现如今有两个版本的 IP 地址,IPv4 和 IPv6,我们首先探讨一下现如今还在广泛使用的 IPv4 地址,后面再考虑 IPv6 。
IPv4 由 32 位正整数来表示,在计算机内部会转化为二进制来处理,但是二进制不符合人类阅读的习惯,所以我们根据易读性
的原则把 32 位的 IP 地址以 8 位为一组,分成四组,每组之间以 .
进行分割,再将每组转换为十进制数。如下图所示
那么上面这个 32 位的 IP 地址就会被转换为十进制的 156.197.1.1。
除此之外,从图中我们还可以得到如下信息
每个这样 8 位位一组的数字,自然是非负数,其取值范围是 [0,255]。
IP 地址的总个数有 2^32 次幂个,这个数值算下来是 4294967296
,大概能允许 43 亿台设备连接到网络。实际上真的如此吗?
实际上 IP 不会以主机的个数来配置的,而是根据设备上的 网卡(NIC)
进行配置,每一块网卡都会设置一个或者多个 IP 地址,而且通常一台路由器会有至少两块网卡,所以可以设置两个以上的 IP 地址,所以主机的数量远远达不到 43 亿。
IP 地址构造和分类
IP 地址由 网络标识
和 主机标识
两部分组成,网络标识代表着网络地址,主机标识代表着主机地址。网络标识在数据链路的每个段配置不同的值。网络标识必须保证相互连接的每个段的地址都不重复。而相同段内相连的主机必须有相同的网络地址。IP 地址的 主机标识
则不允许在同一网段内重复出现。
举个例子来说:比如说我在石家庄(好像不用比如昂),我所在的小区的某一栋楼就相当于是网络标识,某一栋楼的第几户就相当于是我的主机标识,当然如果你有整栋楼的话,那就当我没说。你可以通过xx省xx市xx区xx路xx小区xx栋来定位我的网络标识,这一栋的第几户就相当于是我的网络标识。
IP 地址分为四类,分别是 A类、B类、C类、D类、E类 ,它会根据 IP 地址中的第 1 位到第 4 位的比特对网络标识和主机标识进行分类。
A 类
:(1.0.0.0 - 126.0.0.0)(默认子网掩码:255.0.0.0 或 0xFF000000)第一个字节为网络号,后三个字节为主机号。该类 IP 地址的最前面为 0 ,所以地址的网络号取值于 1~126 之间。一般用于大型网络。B 类
:(128.0.0.0 - 191.255.0.0)(默认子网掩码:255.255.0.0 或 0xFFFF0000)前两个字节为网络号,后两个字节为主机号。该类 IP 地址的最前面为 10 ,所以地址的网络号取值于 128~191 之间。一般用于中等规模网络。C 类
:(192.0.0.0 - 223.255.255.0)(子网掩码:255.255.255.0 或 0xFFFFFF00)前三个字节为网络号,最后一个字节为主机号。该类 IP 地址的最前面为 110 ,所以地址的网络号取值于 192~223 之间。一般用于小型网络。D 类
:是多播地址。该类 IP 地址的最前面为 1110 ,所以地址的网络号取值于 224~239 之间。一般用于多路广播用户。E 类
:是保留地址。该类 IP 地址的最前面为 1111 ,所以地址的网络号取值于 240~255 之间。
为了方便理解,我画了一张 IP 地址分类图,如下所示
根据不同的 IP 范围,有下面不同的地总空间分类
子网掩码
子网掩码(subnet mask)
又叫做网络掩码,它是一种用来指明一个 IP 地址的哪些位标识的是主机所在的网络。子网掩码是一个 32位 地址,用于屏蔽 IP 地址的一部分以区别网络标识和主机标识。
一个 IP 地址只要确定了其分类,也就确定了它的网络标识和主机标识,由此,各个分类所表示的网络标识范围如下
用 1
表示 IP 网络地址的比特范围,0
表示 IP 主机地址的范围。将他们用十进制表示,那么这三类的表示如下
保留地址
在IPv4 的几类地址中,有几个保留的地址空间不能在互联网上使用。这些地址用于特殊目的,不能在局域网外部路由。
IP 协议版本
目前,全球 Internet 中共存有两个IP版本:IP 版本 4(IPv4)
和 IP 版本6(IPv6)
。 IP 地址由二进制值组成,可驱动 Internet 上所有数据的路由。 IPv4 地址的长度为 32 位,而 IPv6 地址的长度为 128 位。
Internet IP 资源由 Internet 分配号码机构(IANA)
分配给区域 Internet 注册表(RIR),例如 APNIC,该机构负责根 DNS ,IP 寻址和其他 Internet 协议资源。
下面我们就一起认识一下 IP 协议中非常重要的两个版本 IPv4 和 IPv6。
IPv4
IPv4 的全称是 Internet Protocol version 4
,是 Internet 协议的第四版。IPv4 是一种无连接的协议,这个协议会尽最大努力交付数据包,也就是说它不能保证任何数据包能到达目的地,也不能保证所有的数据包都会按照正确的顺序到达目标主机,这些都是由上层比如传输控制协议控制的。也就是说,单从 IP 看来,这是一个不可靠的协议。
前面我们讲过网络层分组被称为
数据报
,所以我们接下来的叙述也会围绕着数据报展开。
IPv4 的数据报格式如下
IPv4 数据报中的关键字及其解释
版本字段(Version)
占用 4 bit,通信双方使用的版本必须一致,对于 IPv4 版本来说,字段值是 4。首部长度(Internet Header Length)
占用 4 bit,首部长度说明首部有多少 32 位(4 字节)。由于 IPv4 首部可能包含不确定的选项,因此这个字段被用来确定数据的偏移量。大多数 IP 不包含这个选项,所以一般首部长度设置为 5, 数据报为 20 字节 。服务类型(Differential Services Codepoint,DSCP)
占用 6 bit,以便使用不同的 IP 数据报,比如一些低时延、高吞吐量和可靠性的数据报。服务类型如下表所示
-
拥塞通告(Explicit Congestion Notification,ECN)
占用 2 bit,它允许在不丢弃报文的同时通知对方网络拥塞的发生。ECN 是一种可选的功能,仅当两端都支持并希望使用,且底层网络支持时才被使用。 最开始 DSCP 和 ECN 统称为 TOS,也就是区分服务,但是后来被细化为了 DSCP 和 ECN。 -
数据报长度(Total Length)
占用 16 bit,这 16 位是包括在数据在内的总长度,理论上数据报的总长度为 2 的 16 次幂 - 1,最大长度是 65535 字节,但是实际上数据报很少有超过 1500 字节的。IP 规定所有主机都必须支持最小 576 字节的报文,但大多数现代主机支持更大的报文。当下层的数据链路协议的最大传输单元(MTU)
字段的值小于 IP 报文长度时,报文就必须被分片。 -
标识符(Identification)
占用 16 bit,这个字段用来标识所有的分片,因为分片不一定会按序到达,所以到达目标主机的所有分片会进行重组,每产生一个数据报,计数器加1,并赋值给此字段。 -
标志(Flags)
占用 3 bit,标志用于控制和识别分片,这 3 位分别是- 0 位:保留,必须为0;
- 1 位:
禁止分片(Don’t Fragment,DF)
,当 DF = 0 时才允许分片; - 2 位:
更多分片(More Fragment,MF)
,MF = 1 代表后面还有分片,MF = 0 代表已经是最后一个分片。
如果 DF 标志被设置为 1 ,但是路由要求必须进行分片,那么这条数据报回丢弃
-
分片偏移(Fragment Offset)
占用 13 位,它指明了每个分片相对于原始报文开头的偏移量,以 8 字节作单位。 -
存活时间(Time To Live,TTL)
占用 8 位,存活时间避免报文在互联网中迷失
,比如陷入路由环路。存活时间以秒为单位,但小于一秒的时间均向上取整到一秒。在现实中,这实际上成了一个跳数计数器:报文经过的每个路由器都将此字段减 1,当此字段等于 0 时,报文不再向下一跳传送并被丢弃,这个字段最大值是 255。 -
协议(Protocol)
占用 8 位,这个字段定义了报文数据区使用的协议。协议内容可以在 https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml 官网上获取。 -
首部校验和(Header Checksum)
占用 16 位,首部校验和会对字段进行纠错检查,在每一跳中,路由器都要重新计算出的首部检验和并与此字段进行比对,如果不一致,此报文将会被丢弃。 -
源地址(Source address)
占用 32 位,它是 IPv4 地址的构成条件,源地址指的是数据报的发送方 -
目的地址(Destination address)
占用 32 位,它是 IPv4 地址的构成条件,目标地址指的是数据报的接收方 -
选项(Options)
是附加字段,选项字段占用 1 - 40 个字节不等,一般会跟在目的地址之后。如果首部长度 > 5,就应该考虑选项字段。 -
数据
不是首部的一部分,因此并不被包含在首部检验和中。
在 IP 发送的过程中,每个数据报的大小是不同的,每个链路层协议能承载的网络层分组也不一样,有的协议能够承载大数据报,有的却只能承载很小的数据报,不同的链路层能够承载的数据报大小如下。
IPv4 分片
一个链路层帧能承载的最大数据量叫做最大传输单元(Maximum Transmission Unit, MTU)
,每个 IP 数据报封装在链路层帧中从一台路由器传到下一台路由器。因为每个链路层所支持的最大 MTU 不一样,当数据报的大小超过 MTU 后,会在链路层进行分片,每个数据报会在链路层单独封装,每个较小的片都被称为 片(fragement)
。
每个片在到达目的地后会进行重组,准确的来说是在运输层之前会进行重组,TCP 和 UDP 都会希望发送完整的、未分片的报文,出于性能的原因,分片重组不会在路由器中进行,而是会在目标主机中进行重组。
当目标主机收到从发送端发送过来的数据报后,它需要确定这些数据报中的分片是否是由源数据报分片传递过来的,如果是的话,还需要确定何时收到了分片中的最后一片
,并且这些片会如何拼接一起成为数据报。
针对这些潜在的问题,IPv4 设计者将 标识、标志和片偏移 放在 IP 数据报首部中。当生成一个数据报时,发送主机会为该数据报设置源和目的地址的同时贴上标识号
。发送主机通常将它发送的每个数据报的标识 + 1。当某路由器需要对一个数据报分片时,形成的每个数据报具有初始数据报的 源地址、目标地址和标识号 。当目的地从同一发送主机收到一系列数据报时,它能够检查数据报的标识号以确定哪些数据是由源数据报发送过来的。由于 IP 是一种不可靠的服务,分片可能会在网路中丢失,鉴于这种情况,通常会把分片的最后一个比特设置为 0 ,其他分片设置为 1,同时使用偏移字段指定分片应该在数据报的哪个位置。
IPv4 寻址
IPv4 支持三种不同类型的寻址模式,分别是
- 单播寻址模式:在这种模式下,数据只发送到一个目的地的主机。
- 广播寻址模式:在此模式下,数据包将被寻址到网段中的所有主机。这里客户端发送一个数据包,由所有服务器接收:
- 组播寻址模式:此模式是前两种模式的混合,即发送的数据包既不指向单个主机也不指定段上的所有主机
IPv6
随着断系统接入的越来越多,IPv4 已经无法满足分配了,所以,IPv6 应运而生,IPv6 就是为了解决 IPv4 的地址耗尽问题而被标准化的网际协议。IPv4 的地址长度为 4 个 8 字节,即 32 比特, 而 IPv6 的地址长度是原来的四倍,也就是 128 比特,一般写成 8 个 16 位字节。
从 IPv4 切换到 IPv6 及其耗时,需要将网络中所有的主机和路由器的 IP 地址进行设置,在互联网不断普及的今天,替换所有的 IP 是一个工作量及其庞大的任务。我们后面会说。
我们先来看一下 IPv6 的地址是怎样的
版本
与 IPv4 一样,版本号由 4 bit 构成,IPv6 版本号的值为 6。流量类型(Traffic Class)
占用 8 bit,它就相当于 IPv4 中的服务类型(Type Of Service)。流标签(Flow Label)
占用 20 bit,这 20 比特用于标识一条数据报的流,能够对一条流中的某些数据报给出优先权,或者它能够用来对来自某些应用的数据报给出更高的优先权,只有流标签、源地址和目标地址一致时,才会被认为是一个流。有效载荷长度(Payload Length)
占用 16 bit,这 16 比特值作为一个无符号整数,它给出了在 IPv6 数据报中跟在鼎昌 40 字节数据报首部后面的字节数量。下一个首部(Next Header)
占用 8 bit,它用于标识数据报中的内容需要交付给哪个协议,是 TCP 协议还是 UDP 协议。跳限制(Hop Limit)
占用 8 bit,这个字段与 IPv4 的 TTL 意思相同。数据每经过一次路由就会减 1,减到 0 则会丢弃数据。源地址(Source Address)
占用 128 bit (8 个 16 位 ),表示发送端的 IP 地址。目标地址(Destination Address)
占用 128 bit (8 个 16 位 ),表示接收端 IP 地址。
可以看到,相较于 IPv4 ,IPv6 取消了下面几个字段
- 标识符、标志和比特偏移 :IPv6 不允许在中间路由器上进行分片和重新组装。这种操作只能在端系统上进行,IPv6 将这个功能放在端系统中,加快了网络中的转发速度。
- 首部校验和 :因为在运输层和数据链路执行了报文段完整性校验工作,IP 设计者大概觉得在网络层中有首部校验和比较多余,所以去掉了。 IP 更多专注的是快速处理分组数据 。
- 选项字段 :选项字段不再是标准 IP 首部的一部分了,但是它并没有消失,而是可能出现在 IPv6 的扩展首部,也就是下一个首部中。
IPv6 扩展首部
IPv6 首部长度固定,无法将选项字段加入其中,取而代之的是 IPv6 使用了扩展首部
扩展首部通常介于 IPv6 首部与 TCP/UDP 首部之间,在 IPv4 中可选长度固定位 40 字节,在 IPv6 中没有这样的限制。IPv6 的扩展首部可以是任意长度。扩展首部中还可以包含扩展首部协议和下一个扩展字段。
IPv6 首部中没有标识和标志字段, 对 IP 进行分片时,需要使用到扩展首部 。
具体的扩展首部表如下所示
下面我们来看一下 IPv6 都有哪些特点
IPv6 特点
IPv6 的特点在 IPv4 中得以实现,但是即便实现了 IPv4 的操作系统,也未必实现了 IPv4 的所有功能。而 IPv6 却将这些功能大众化了,也就表明这些功能在 IPv6 已经进行了实现,这些功能主要有
- 地址空间变得更大 :这是 IPv6 最主要的一个特点,即支持更大的地址空间。
- 精简报文结构 : IPv6 要比 IPv4 精简很多,IPv4 的报文长度不固定,而且有一个不断变化的选项字段;IPv6 报文段固定,并且将选项字段,分片的字段移到了 IPv6 扩展头中,这就极大的精简了 IPv6 的报文结构。
- 实现了自动配置 :IPv6 支持其主机设备的 状态和无状态 自动配置模式。这样,没有
DHCP 服务器
不会停止跨段通信。 - 层次化的网络结构 : IPv6 不再像 IPv4 一样按照 A、B、C等分类来划分地址,而是通过 IANA -> RIR -> ISP 这样的顺序来分配的。IANA 是国际互联网号码分配机构,RIR 是区域互连网注册管理机构,ISP 是一些运营商(例如电信、移动、联通)。
- IPSec :IPv6 的扩展报头中有一个认证报头、封装安全净载报头,这两个报头是 IPsec 定义的。通过这两个报头网络层自己就可以实现端到端的安全,而无需像 IPv4 协议一样需要其他协议的帮助。
- 支持任播 :IPv6 引入了一种新的寻址方式,称为任播寻址。
IPv6 地址
我们知道,IPv6 地址长度为 128 位,他所能表示的范围是 2 ^ 128 次幂,这个数字非常庞大,几乎涵盖了你能想到的所有主机和路由器,那么 IPv6 该如何表示呢?
一般我们将 128 比特的 IP 地址以每 16 比特为一组,并用 :
号进行分隔,如果出现连续的 0 时还可以将 0 省略,并用 ::
两个冒号隔开,记住,一个 IP 地址只允许出现一次两个连续的冒号。
下面是一些 IPv6 地址的示例
- 二进制数表示
- 用十六进制数表示
- 出现两个冒号的情况
如上图所示,A120 和 4CD 中间的 0 被 :: 所取代了。
另外,我自己肝了六本 PDF,微信搜索「程序员cxuan」关注公众号后,在后台回复 cxuan ,领取全部 PDF,这些 PDF 如下