目录
1. 前置性认识
2. IP协议
3. IP协议头格式
3.1. 4位版本
3.2. 4位首部长度
3.3. 8位服务类型
3.4. 16位总长度
3.5. 8位生存时间 TTL
3.6. 8位协议
3.7. 16位首部检验和
3.8. 32位源IP和32位目的IP
4. 分片问题
4.1. 为什么要分片
4.2. 分片是什么
4.2.1. 为什么要组装呢?
4.3. 如何实现分片
4.4. 分片 demo,理解分片
4.5. 分片的坏处
5. 网段划分
5.1. DHCP 技术
5.2. 网段划分
5.3. 特殊的IP地址
6. IP地址的数量限制
7. 私有IP地址和公网IP地址
8. 路由
1. 前置性认识
我们现在已经对传输层以及相关协议有了一定的认识,可是现在有一个问题,传输层真的把数据发送到网络了吗?
- 答案是:没有,传输层并没有将数据发送到网络中,只是将数据向下交付给了网络层;
- 传输层的主要任务是提供端到端的通信策略。比如TCP,在端到端的通信中,提供可靠性策略。
那么IP协议解决什么问题呢?
- IP协议属于网络层,网络层解决的是在网络中如何有效地路由数据,以便数据能够从一个主机传输到另一个主机;
- 具体到IP协议,IP协议提供一种能力,将数据跨网络从一个主机传输到另一个主机的能力。
IP协议有这种能力, 但一定能做到吗?
答案:不一定,只是代表着IP协议有非常高的概率,将数据从一端传输到另一端,并不能保证每一次数据传输都能成功完成。
2. IP协议
基本概念:
- 主机:配有IP地址,不能进行路由控制的设备;
- 路由器: 即配有IP地址, 又能进行路由控制;
- 节点: 主机和路由器的统称;
3. IP协议头格式
IP协议头格式如下:
首先,上面这个IP协议报头结构,在Linux本质上就是一个位段,因此,我们所说的创建一个报头,体现在内核层面,就是创建一个位段对象;
其次,这个有效载荷具体是什么呢? 假设,应用层采用的协议是HTTP,传输层采用的协议是TCP,那么此时IP的有效载荷是什么呢? 如下:
在我们认识一个新协议的时候,首先需要考虑两个问题:
第一个问题:如何封装和解包,即如何将IP数据报中的报头和有效载荷分离呢?
第二个问题:如何交付呢?
如何封装和解包,即如何将IP数据报中的报头和有效载荷分离呢?
IP的报头是由两部分组成的, 固定长度的20字节 + 选项部分,选项部分可以没有;
在固定长度的20字节中有,4位首部长度,它可以计算出报头的整体大小 (20字节 + 选项);不仅如此,在这20字节中还有16位总长度,它代表着一个IP数据报的整体大小;
可是有一个问题,4位首部长度,其数据范围是 0000 - 1111,即 0 - 15,如何能表示20字节以上的数据呢?
事实上,这个4位首部长度是有单位的, 其单位是4字节,即首部长度的数据范围是 0 - 15,但能表示的字节范围是 0 - 60;
假设四位首部长度为 x;
x 的最小值:x * 4 = 20,即不包含选项,得出 x = 5,即 0101;
x 的最大值:x * 4 = 60;包含选项,得出 x = 15,即 1111;
故实际上,首部长度的范围是:0101 - 1111;
有了上面的认识,我们就可以将IP数据报的报头和有效载荷分离了,大致过程如下:
- 首先读取固定长度的20字节,分别获得4位首部长度和16位总长度;
- 如果4位首部长度 * 4 等于 20,固定20字节就是报头,剩下的就是有效载荷;
- 如果4位首部长度 * 4 大于 20,那么4位首部长度 * 4 - 20,就是选项的字节数,读取选项后,剩下的就是有效载荷;
- 最后,根据16位总长度 - 4位首部长度 * 4 就是有效载荷的长度;
至此,我们就可以将IP数据报的报头和有效载荷分离,即是解包的过程,解包一旦解决,封装就是水到渠成的事情了。
如何交付呢?
在IP报头的固定20字节中,有着8位协议,和32位目的IP地址,通过目的IP地址可以找到目标主机,再根据8位协议决定将数据交付于传输层的哪一个协议,传输层再根据目的端口,将数据交给特定进程。
3.1. 4位版本
4位版本用于指定IP协议的版本,对于 IPv4 而言,就是4;如果是 IPv6 ,就是6;
IPv4 版本的IP协议,用32位比特位来标识IP地址;
IPv6 版本的IP协议,用128位比特位来标识IP地址;
目前主流仍然是 IPv4,原因其一是 IPv4 和 IPv6 并不兼容,这意味着在 IPv4 网络上无法直接运行 IPv6,反之亦然。其二,IPv4 有特定的方案来解决IP地址不足的问题,比如NAT (Network Address Translation) 技术,因此 IPv6 在全球的推行是较为缓慢的。
3.2. 4位首部长度
4位首部长度,单位是4字节, 即4位首部长度 * 4 = IP报头的整体大小。
3.3. 8位服务类型
8位服务类型 (Type Of Service):3位优先权字段 (已经弃用),4位TOS字段,和1位保留字段 (必须置为0),4位TOS分别表示:最小延时,最大吞吐量,最高可靠性,最小成本,这四者互相冲突,只能选择一个。
3.4. 16位总长度
16位总长度,单位为字节,代表着一个IP数据报的整体大小。
通过16位总长度就可以计算有效载荷的长度,16位总长度 - 4位首部长度 * 4 = 有效载荷的长度;
3.5. 8位生存时间 TTL
为了防止一个IP数据段在网络中出现路由循环的情况,给每一个IP数据端设置生存时间 (TTL --- Time To Live)。
这个8位生存时间具体就是数据报到达目的地的最大报文跳数,一般是64,每次经过一个路由器,TTL减1,如果一直减到0,还没到达目标主机,那么该IP数据段就被丢弃,防止出现了路由环路,数据报也不会用在网络中一直循环。
为什么要有8位生存时间呢?
因为,网络层无法保证数据一定会从一台主机传输到另一台主机,如果IP数据报在路由过程中出现问题,例如由于路由器的故障或配置错误导致IP数据报不能正确转发,没有生存时间限制的话,这些数据报可能会在网络中无限期地循环,占用网络资源,长此以往,导致网络拥塞甚至瘫痪。
通过设置生存时间,IP数据报在经过一定数量的路由器后会被丢弃,从而防止IP数据报无限制地在网络中传播,这样可以有效防止网络资源浪费,确保网络的正常运行。
从上面我们也可以看出,这里的生存时间实际上就是一个计数器,代表着数据在网络中经过的最大路由器数量,也就是最大跳数。
3.6. 8位协议
8位协议代表的就是上层 (传输层) 使用的是什么协议,TCP 或者 UDP,换言之,8为协议就代表的是IP协议的有效载荷要交付给上层的哪一个协议呢?
3.7. 16位首部检验和
16位校验和字段用于检查IP报头是否在传输过程中损坏。
如果校验和验证失败,即报头数据被篡改或损坏,接收端会丢弃该IP数据报。
如果IP数据段被丢弃,那么上层 (传输层) 也就不会获得ACK应答,故等待特定时间后,进行重传。
3.8. 32位源IP和32位目的IP
32位的源IP地址和32位的目的IP地址分别指示了IP数据报的发送者和接收者;这些地址在路由过程中被用来确定数据报的下一跳路径,以确保数据报能够正确地传输到目的地。
IP 数据报是会携带32位源IP和32位目的IP的,而IP数据报中是包含传输层数据段的,比如TCP数据段,而TCP数据段是包含目的端口和源端口的,因此,在网路层看来,一个完整的IP数据报,是即携带了源端口和目的端口以及源IP和目的IP,故能锁定特定主机和该主机上的特定进程。
从这里我们也可以看出,端口号是由传输层提供的,而IP地址是由网络层提供的,其次,在我们以前写套接字的时候,是会将点分十进制的IP地址转化为4字节的IP地址,为什么呢?
因为网络层在操作系统,即网络层的相关约定 (协议) 是操作系统制定的,换言之,4字节的IP地址同来构成IP报头,这是操作系统的硬性要求,上层要用操作系统提供的功能,就必须遵守操作系统的协议。
事实上,在网络通信的过程中,只有双方主机才会在应用层和传输层工作,而中间的路由器只工作在网络层和数据链路层,虽然中间的路由器可以有传输层,甚至应用层,但在网络通信的过程中,不需要。
如下:
4. 分片问题
4.1. 为什么要分片
- 上层用户发送数据时,应用层添加报头形成数据包,将数据包向下交付传输层,由传输层来提供端到端的传输策略,传输层封装报头形成数据段,向下交付给网络层,网络层提供数据从端到端的能力,网络层将数据添加报头形成数据报,向下交付给数据链路层;
- 但是数据链路层由于物理特征的原因, 一般无法转发太大的数据,即据链路层通常有一个最大传输单元(MTU),即一次能够发送的数据帧的最大有效载荷的长度,一般是 1500 字节;
- 如果网络层需要向下交付的数据大小超过了数据链路层的MTU,那么网络层自身就需要进行数据分片,对端网络层收到后,也需要验证分片是否完整及其数据组装工作。
- 数据分片是在网络层实现的,上层 (传输层) 不关心,传输层向下交付的数据段大小通常是由滑动窗口决定的 ( 从这里也可以看出,网络层自身无法决定传输数据有多大,而是由传输层决定的 ),即传输层并不直接参与分片和组装过程,它只负责将数据段向下交付给网络层;
- 因此,对于传输层而言,向下交付的是一个2500字节的数据段,对端传输层也必须要收到一个2500字节的数据段,故数据分片也必须要有相应的组装工作;
- 那么是谁组装呢? 对端的网络层进行数据组装工作;
- 因此,为了支持IP协议进行数据分片和组装,有了这三个字段,分别是16位标识、3位标志、13位片偏移;
- 发送端的网络层负责将较大的数据报进行分片,添加IP报头或者修改原IP报头中的相关字段;
- 接收端的网络层则负责根据相关字段将分片重新组装成原始的IP数据报,解包后,向上交付给传输层;
可能会有这样的疑惑,如果网络层不处理数据分片和组装,而是将数据直接向下交付给数据链路层,让数据链路层自行处理,如果太大了,那么让数据链路层进行数据分片,这种方案行不行呢?
不行,因为数据链路层做不到,或者成本太高;
- 后续我们会知道,不同的数据链路层协议(如以太网、Wi-Fi等)在帧的格式和处理上存在差异。将数据分片和组装的工作交由数据链路层会导致需要针对每种链路层协议实现不同的分片和组装方案,增加了复杂性和成本;
- 而网络层是属于操作系统范畴的,是所有网络通信的基础,如果将数据分片和组装工作交给网络层,即操作系统,操作系统就可以统一管理和实现这些功能,降低了实现和维护的成本;
- 因此,对于数据链路层而言,只需要规定一个自己所能传输的数据帧的有效载荷的最大值即可,即MTU,就OK了,当上层 (网络层) 准备将数据向下交付给数据链路层时,如果数据容量大于MTU,那么进行数据分片即可,数据链路层自身不关心数据分片和组装工作。
- 从上面的理解链路中,我们可以知道,站在网络层的视角,它无法决定上层 (传输层) 传输数据有多大,但它负责将传输层交付的数据向下交付给数据链路层;
- 即传输层向网络层交付多大的数据,网络层就需要将这些数据向下交付给数据链路层,而数据链路层又由于物理特征原因,一次无法传输太大数据,即存在着MTU,因此,网络层就有了数据分片的需求;
- 而这就是数据分片的直接原因,既然有分片的需求,那么也必然要存在着数据组装的工作。
同时,在学习滑动窗口时,我们一直有一个疑惑,假如接收端的接受能力是4096Byte,发送方的滑动窗口也是4096Byte,暂不考虑网络情况 (即拥塞窗口),为什么发送方不直接构建一个数据段,将这些数据一起发送给对端,因为我们知道,网络传输本质上就是一个IO过程,很明显,一次IO总比多次IO效率高啊,可是,事实上,滑动窗口依旧将数据分成多个数据段向下交付,为什么呢?
这也是因为数据链路层的限制 (MTU),数据链路层一次性可传输的数据是有限制的,如果太大,网络层就需要做分片的工作,而后续我们会知道,分片这个动作,操作系统实际上是不愿意做的 (至于为什么,稍后再说),因此,TCP在构建TCP数据段时,也会考虑底层的限制,具体就是,TCP会有数据段的有效载荷的最大长度 (MSS,在数据链路层具体解释),换言之,底层的限制是会影响上层的处理的。
4.2. 分片是什么
数据分片是将大于MTU的IP数据报分割成多个,满足条件的IP数据报。
数据分片的行为是网络层做的, 同样,数据组装的行为也必须由对端网络层进行。
4.2.1. 为什么要组装呢?
- 站在传输层角度,发送方向下交付的是一个完整的数据段,而对端传输层接收到的也应该是一个完整的数据段;
- 因此,如果发送端的网络层进行了数据分片,对端的网络层就需要验证分片是否完整以及分片组装工作,以确保接收到的数据是完整的、正确的数据段;
- 同时,这也说明了数据分片和组装对于传输层来说是透明的,即传输层不关心数据在网络层的分片和组装过程,它只需要确保向下交付的数据段是完整的;
- 这种分工设计,使不同协议层的功能解耦,降低了系统的复杂性和维护成本。
4.3. 如何实现分片
IP协议通过三个字段来实现数据分片和组装的:
- 16位标识: IP数据报的唯一标识。 如果IP数据报在网络层被分片了,每一个分片都是一个IP数据报,所有的IP数据报中的16位标识是一致的;
- 3位标志字段:第一位,保留 (现在不用,以后可能会用);第二位,如果置为1,则表示禁止分片,这时候,如果IP数据报长度超过MTU,数据链路层则将该IP数据报直接被丢弃;第三位,表示 "更多分片",如果置为1,则表示后续还有分片;
- 13位片偏移:其代表着分片相当于原始IP数据报开始处的偏移量。其实就是在表示当前分片在原报文中出在哪一个位置,例如,第一个分片的片偏移就是0。
要进行数据分片, 首先需要具有识别不同的IP数据段
如何识别呢?在IP协议中,通过16位标识识别不同的IP数据段。
- 当一个IP数据报进行分片后,它会被分成多个IP数据段,每个数据段都会带有相同的16位标识;
- 如果一个IP数据报没有被分片,那么每个数据段的标识字段将是唯一的,因为它们都来自于不同的IP数据报。
至此,我们就可以通过16位标识来区分不同的IP数据报;
同时,经过我们上述的描述,我们也发现,分片后得到的IP数据段是需要16位标识字段的,即分片后得到的每个IP数据段都需要包含IP报头,因此,分片也可能包含着添加IP报头的动作。
或许,我们会有这样的疑问,标识只有16位,这个数字并不是很大,有没有一种可能,标识会被重复呢?即两个不同的IP数据段 (未经过分片) 的标识是一样的?
答案是,不存在这种情况。网络层收到数据后,通常会尽快将数据向上交付,而不会对大量数据进行积压。因此,在正常情况下,不太可能会出现大量数据在网络层积压,导致标识重复的情况。
如何判断一个IP数据报是否被分片了呢?
很简单,规则如下:
- 如果更多分片标志位被置为1,那么就是一个被分片的IP数据报;
- 如果更多分片标志位被置为0,但是13位片偏移不是0,那么说明其也是一个被分片的IP数据报,且是最后的一个分片;
- 如果更多分片标志位被置为0,且13位片偏移是0,那么说明其是一个未被分片的IP数据报,即是一个完整的IP数据报。
当然,我们也可以换个角度:
- 如果13位片偏移不为0,那么该IP数据报一定是一个分片;
- 如果13位片偏移为0, 且更多分片标志位是1,则该IP数据报也是一个分片;
- 如果13位片偏移为0, 但更多分片标志位是0,那么该IP数据报是未被分片的,即是一个完整的IP数据报。
至此,我们就可以通过更多分片标志位和13位片偏移来判定一个IP数据报是否被分片了。
当网络层获得了一批的IP数据报,网络层就可以根据上面的方式,区分出被分片的IP数据报,并将相同标识的IP数据报放在一起,以便于后续验证分片是否完整和分片组装工作。
现在可以判断哪些IP数据报是被分片了的,那么如何判断哪些分片是开始,哪些分片是中间,那些分片是结尾呢?
- 开始:更多分片标志位被置为1,13位片偏移被置为0;
- 中间:更多分片标志位被置为1,13位片偏移不是0;
- 结尾:更多分片标志位被置为0,13位片偏移不是0。
可是中间的IP数据报可能会有多个, 网络层怎么确定所有分片都获得了呢?即验证分片是否完整。
- 很简单,前一个分片的片偏移 + 前一个分片的长度 (这个长度是原IP数据的大小,不包含新增的IP报头) = 下一个分片的片偏移;
- 接收方可以按照片偏移进行升序排序,并验证每个分片的片偏移是否与前一个分片的片偏移加上前一个分片的长度相匹配。
- 如果所有分片的片偏移都按照规则递增,并且与前一个分片的片偏移加上前一个分片的长度相匹配,那么接收方可以确信已经接收到了所有分片并可以成功重组原始的IP数据报。
- 因此,接收端的网络层可以通过上述规则验证分片是否完整,如果完整,在将多个分片进行组装,组装后,对IP数据报解包,将数据向上交付给传输层;
- 如果验证失败,即某个分片丢失,那么就不进行组装工作,将相关分片丢弃即可。
可以看到,通过这三个字段 (16位标识、3位标志、13位片偏移),就可以完成分片和组装工作,下面我们通过一个分片demo,再理解下分片的过程。
4.4. 分片 demo,理解分片
假设网络层向下交付的数据报的大小是3000 byte,而数据链路层的MTU是1500 byte,因此此时网络层自身就需要进行数据分片。
首先,如果没有分片,那么一定是一个完整的IP数据报;
那么如果分片了,是每一个分片都要有IP报头,还是只要第一个分片有就OK了,其他分片不需要呢?
- 很明显,为了让接收端有能力验证分片是否完整以及对分片进行组装,必须要求所有的分片都要有IP报头;
- 因为16位标识、3位标志、13位片偏移都是IP报头中的字段,没有这三个报头字段,接收端将无法正确验证分片是否完整,也无法正确地将分片组装成原始的完整IP数据报;
- 故所有的分片都是一个IP数据报,包含IP报头和有效载荷。
当对IP数据报分片后,第一个分片使用原来的IP报头吗?
- 会使用,但会修改原IP报头中的一些字段;
- 因为IP数据报分片后,此时这个原始IP报头中的属性无法正确表示第一个分片,比如16位总长度、更多分片标志等等字段都需要修改;
- 因此,虽然第一个分片会使用原始的IP报头,但会对相关字段作出修改。
就目前我们的认识,分片后,所有的分片都是一个IP数据报,都需要IP报头。
- 对于第一个分片而言,使用的是原始IP数据报的IP报头,只不过会对相关字段作出更改;
- 对于其他分片而言,需要自己新增IP报头,这些新增的IP报头所占的字节,并不算入其他分片的13位片偏移中,因为片偏移代表的是分片在原始IP数据报中的偏移量 (不论是在分片过程还是在组装过程),不包括新增的IP报头。
分片的过程如下:
有了分片的过程,组装的过程就顺理成章了。
4.5. 分片的坏处
记住一点,分片的行为不是主流 (不建议分片),大多数的IP数据报是不需要进行分片的。
为什么呢?换言之,分片的坏处是什么呢?
众所周知,网络传输是有一定概率丢包的,如果分片了,对于接收端网络层而言,它必须收到所有的分片,只要丢了其中的某一个,这次传输都是失败的 (需要重传),所有分片都会被丢弃,因此,分片实质上是增加了丢包概率,也正因为如此,操作系统内部是不愿意作分片的,体现上就是传输层的MSS,但是,我们知道,在跨网络传输中,会经过不同的设备,而不同的设备的MTU可能不一样,因此,分片行为在所难免,但是传输层的MSS可以避免频繁分片的情况。
5. 网段划分
IP地址分为两个部分,网络号和主机号。
- 网络号:本质上标识的是不同的网段,不同的网段,其网络号不一致;
- 主机号:本质上标识的是不同的主机,在同一网段中,主机之间具有相同的网络号,但是必须有不同的主机号。
- 在一个网段内,本质上就是将相同网络号的主机放在了一起;
- 如果一个网段新增一台主机,则这台主机的网络号和这个子网的网络号一致,但是主机号必须不能和子网中的其他主机重复。
- 路由器本质上也是特定一个子网的主机, 即也要配置IP地址;
- 路由器可以进行跨网络转发数据,因此路由器一定至少要连接2个子网,路由器也就相当于同时在两个子网中,因此路由器需要配置多个IP地址 (认为路由器有多张网卡就行);
- 路由器一般是一个子网中的第一台设备,一般它的IP地址都是:网络号.1,但不是绝对的;
- 路由器功能,主要是IP报文的转发,但是路由器的功能不仅局限于此,比如构建子网 (局域网) 和管理IP地址等功能;
5.1. DHCP 技术
现在我们知道,如果要进行网络传输数据,那么必须要有IP地址 (没有IP地址,则无法进行定位目标主机), 而对于一个子网而言,可能会存在众多IP地址,因此IP地址也是需要被管理起来的,而事实上,手动管理子网内的IP地址,是一个相对复杂的事情,因为在一个子网中,随时都可能存在新的主机连接该子网 (分配IP地址),或者和该子网断开连接 (释放IP地址),因此:
- 有一种技术叫做 DHCP (Dynamic Host Configuration Protocol),它是一种网络协议,它允许网络中的设备自动获取IP地址、子网掩码、网关地址等网络配置信息,从而无需管理员手动配置这些信息;
- DHCP 通过 DHCP 服务器来管理IP地址的分配和释放;
- 一般情况下,路由器都具有 DHCP 服务器功能,因此,路由器可以在局域网内充当DHCP 服务器,自动为连接到该网络的设备分配 IP地址等配置信息。这样一来,新增设备加入网络时,它们可以向路由器发送 DHCP 请求,路由器则会自动为它们分配 IP地址,使得网络管理更加方便和高效。
5.2. 网段划分
在IP协议中,IP地址是用32个比特位来表示的,其最大值就是 4,294,967,295,接近43亿,但是在当今网络世界中,是远远不够的,换言之,IP地址是一种有限的资源,而有限的资源是会被 (各种组织、国家) 竞争的,因此,为了更合理的分配IP资源,IP地址实际上是会被划分的,而又因为,IP地址分为网络号和主机号,因此,在过去曾经提出一种划分网络号和主机号的方案,把所有IP地址分为五类,如下图所示:
- A类IP地址的范围:0.0.0.0 到 127.255.255.255;
- B类IP地址的范围:127.0.0.0 到 191.255.255.255;
- C类IP地址的范围:192.0.0.0 到 223.255.255.255;
- D类IP地址的范围:224.0.0.0 到 239.255.255.255;
- E类IP地址的范围:240.0.0.0 到 247.255.255.255;
但随着互联网的发展,这种方案的局限性就显现出来,例如,A类IP地址,可能会造成大量浪费,而其他类的IP地址可能供不应求。
- 对于A类地址而言,它的主机号是24位,即 2 ^ 24,大约是1600w,而在实际的网络架设中,很少或者几乎不存在容纳如此之多的主机的情况,因此A类的IP地址会被大量浪费;
- 对于C类地址而言,它的主机号是8位,最多 2^8个主机,即256台主机,对于一个网络而言,可能会出现供不应求的状态;
因此,这种方案的设计在当今网络环境中,不太合理。
补充一下:
申请A类、B类、C类等地址,一般情况下都不是个人申请,而是由特定组织或者机构申请的,比如运营商。
可能会有这样的疑惑,有些组织可能实力比较弱,会不会被恶意针对呢?即不给他们分配IP地址。
首先,网络是一门技术,技术不牵扯政治,作为网络而言,它的愿景就是让更多人进入网络中,参与网络,从而通过网络带来各种收益,换言之,网络的内驱力就驱动着让更多人接触网络,因此,一般情况下,并不会因为组织规模或其他因素而拒绝分配IP地址。
实际上,我们可以看出,上面的方案不太合理,因为当今网络环境中,IP地址本身就不够用了,而A类,甚至B类地址,还可能存在着大量浪费IP地址的情况,这显然是不能容忍的,因此,提出了新的解决方案,称之为CIDR (Classless Inter-Domain Routing):
- 在分类划分法的基础之上,引入一个额外的子网掩码来区分网络号和主机号;
- 子网掩码是一个32位的正整数,通常用一串 "0" 来结尾;
- 假设子网掩码是 255.255.255.0,实际上就是 1111 1111 1111 1111 1111 1111 0000 0000;
- 将IP地址和子网掩码进行 "按位与" 操作,得到的结果就是网络号;
- 未来,我们就可以通过调整子网掩码中 1 的个数,来得到不同的网络号,子网掩码中 1 的个数越多,其网络号的位数就越多,即对应的网络就更小,可以容纳的主机数量也就越少,换言之,随着子网掩码 1 的个数的增大会导致网络不断变得更具体和更小,即这是一个收敛的过程;
- 网络号和主机号的划分与这个IP地址是A类、B类还是C类无关。
我们用实例来理解子网掩码的作用:
- 192.168.254.32/24;
- 上面代表用前24位来标定网络号,即子网掩码的前24位都是1,后8位为0,即255.255.255.0;
- IP地址为:192.168.254.32;
- 子网掩码和IP地址进行按位与,得到网络号:192.168.254.0;
- 因为此时主机号的位数是8位, 故主机号的范围 [0, 255],因此子网地址的范围:[192.168.254.0, 192.168.254.255];
如图所示:
补充一点,虽然上面的子网地址范围是 [192.168.254.0, 192.168.254.255],但是,在一个子网中,不会存在主机号为0和主机号为255的主机,这两个被用来作为特殊用途:
- xxx.xxx.xxx.0,主机号为0,我们称之为网络号;
- xxx.xxx.xxx.255,主机号为255,我们称之为广播号。
接下来,我们再看一个例子
- 192.168.254.68/28;
- 上面代表用前28位来标定网络号,即子网掩码的前28位都是1,后4位为0,即255.255.255.240;
- IP地址为:192.168.254.68;
- 子网掩码和IP地址进行按位与,得到网络号:192.168.254.64;
- 因为此时主机号的位数是4位, 故主机号的范围 [0, 15],因此子网地址的范围:[192.168.254.64, 192.168.254.79];
如图所示:
从上面的两个例子我们也可以看出,随着子网掩码中1的位数的增大,其子网地址的范围就更小,即所表示的网络就更小,因此,这是一个收敛的过程,我们就可以通过不断的增加子网掩码中1的位数,减少主机号的位数,进而缩小网络范围,最终锁定目标网络。
事实上,网段划分并不是只能进行一次,通过给不同路由器不同位数的子网掩码,就能看到不同的网络号,进而不断的进行网段划分,锁定目标网络。
具体来说,当数据在进行路由时,通过不断的网段划分,数据会进入越来越小的子网中,实质上就是子网掩码中 1 的位数不断增大,进而得到的网络号的位数不断增大,主机号的位数不断变小,进而将目标网络限定在一个更精确的范围,当找到目标网络时,就可以通过主机号在将数据交付于特定的主机。
我们也能看出,查找的过程分两步:先找目标网络,再找目标主机;
而实际上,之所以先查找目标网络是因为,查找的本质是排除,排查网络的效率会比排查主机的效率更高,因为,每当确定一个目标网络时,就可以排除其他网络,进而可以排除一大批主机,因此提高了效率,而这就是先查找目标网络的原因。
5.3. 特殊的IP地址
在一个局域网中,如果主机号全为0,就是这个局域网的标识,即网络号;
在一个局域网中,如果主机号全为1,就成为了广播地址,用于给同一个链路中相互连接的所有主机发送数据报;
127.* 的IP地址用于本机环回 (loop back) 测试,通常是 127.0.0.1;
6. IP地址的数量限制
现在我们知道,IP地址 (IPv4) 是一个32位的整数,那么一共只有 2^32 个地址,接近43亿,而在网络通信中 (底层采用的是TCP/IP),每一台主机都需要有IP地址。
可是,在当今网络环境中,入网的设备可太多了,手机、电视、甚至汽车等都会入网,而这些设备都需要一个IP地址,甚至,对于路由器而言可能会需要多个IP地址,因此,IP地址在当前网络环境中,是远远不够的。
虽然 CIDR 在一定程度上缓解了 IP 地址不足的问题,因为它减少了浪费,提高了利用率,但是 IP 地址的绝对上限并没有增加。
关于CIDR减少IP地址浪费,提高利用率,如何理解呢?
- 比如,如果没有CIDR,对于一个A类地址而言,它只有7位网络号,但主机号却高达24位,这就表明在一个网段中,最多可以容纳 2 ^ 24 个主机,这在实际的网络架设中,是很少出现的,在实际中,一个网络不会容纳如此多的主机,换言之,A类的IP地址就被大量浪费了;
- 而如果有了CIDR,我们可以在A类IP地址基础之上,继续对IP地址划分。比如,我们可以通过子网掩码重新定义网络号的位数,通过增加网络号的位数,缩减主机号的位数,就可以做到:可以构建更多的子网,同时,子网中所容纳的最大主机量也会得到减少,也就减少了IP地址的浪费;
因此,CIDR 通过子网掩码灵活调整网络号和主机号的位数,有效地解决了传统的IP地址划分方式所存在的浪费问题;
可是, 尽管 CIDR 解决了IP地址浪费的问题 (提高IP地址利用率),但是IP地址的上限不足问题没有得到解决,这时候就会有三种方式来解决IP地址不足的问题:
- 动态分配IP地址:只给接入网络的设备分配IP地址,因此同一个MAC地址的设备,每次接入互联网中,得到的IP地址不一定是相同的,这种共享思路也没有从根本上解决IP地址不足的问题;
- NAT技术:网络地址转换 ( Network Address Translation ) 技术是一种在局域网(LAN)和广域网(WAN)或互联网之间转换IP地址的方法。后面要详谈的;
- IPv6:首先,IPv6和IPv4是两个互不相干的协议,彼此间不兼容,IPv6用128个比特位来表示一个IP地址,2 ^128 是一个天文数字,足以给全世界的所有需要IP的设备分配IP地址了,但是目前而言,IPv6在全球仍未普及。
7. 私有IP地址和公网IP地址
IP 地址被硬性的划分成为公网IP和私有IP地址。
如果一个组织内部组建局域网,IP地址只用于局域网内的通信,而不直接连接到公网,理论上,使用任意的IP地址都可以,但是 RFC 1918 规定了用于组建局域网的私有IP地址必须是下面的三种:
- 10.0.*:10.0.0.0 到 10.255.255.255, 前8位都是网络号,共 2 ^ 24 个地址;
- 172.16.* 到 172.31.*:172.16.0.0 到 172.31.255.255,前12位是网络号,共 2 ^ 20 个地址;
- 192.168.*:192.168.0.0 到 192.168.255.255,前16位是网络号,共 2 ^ 16 个地址。
只要是上面范围的IP地址,都称之为私有IP,其余的则称之为全局IP (公网IP);
记住,私有IP不能出现在公网中。
私有IP不能出现在公网中,为什么呢?
首先,我们需要知道,在不同的局域网中,是可以出现相同的私有IP的,换言之,私有IP在公网的视角中是多个的,因此,如果私有IP地址出现在公网中,将导致路由器无法正确转发数据包,因为公网上的路由器通常只负责转发公网IP地址的数据包。
大部分用户所使用的IP全部是私有IP (因为用户接触的大部分是局域网,而并不是公网),目前,我们所接触的公网IP就是云服务器的公网IP,比如:
接下来,我们需要了解一下一个用户是如何上网的呢?
一般分为三个步骤,如下:
光纤入户和设备连接:用户想要上网,首先需要 (运营商的工作人员) 安装光纤入户,然后连接调制解调器(俗称猫)和家用路由器。调制解调器将光纤传输的 (模拟) 信号转换为数字信号,以便路由器可以识别和处理;
付费和账户验证:在连接设备之后,用户需要向运营商支付费用以获取互联网服务。通常,路由器会有一个预设的初始账户和密码 (用于上网),用户可以使用这些信息登录到路由器的管理界面,并根据运营商的指示完成付费和账户验证过程。一旦支付完成,运营商会激活用户的互联网服务,允许路由器访问互联网;
构建局域网:同时,路由器还会在用户家庭内构建局域网(LAN),允许多个设备通过有线或无线连接共享互联网连接。通常情况下,路由器会有一个Wi-Fi网络名称(SSID)和密码 (验证用户),只有知道这些信息的人才能连接到该路由器的网络。
接下来再谈谈对运营商的理解。
在网络世界中,有一件事情非常重要,那就是网络基础设施建设,比如机房、基站、拉光纤、信号塔等等基础设施的建设,而这些工作都是由运营商完成的。
为什么在一些偏远地区,还能够上网、刷手机呢? 本质是因为运营商将这些基础设施建立在全国的各个地方;
正是因为运营商对基础设施的投入,才使得越来越多的人接触网络,才使得网络不断发展,才能孕育出一大批的互联网公司,而这些公司才能诞生出更多的岗位,为社会提供更多的就业机会,带来更多的收益,进而支持运营商投入更多资金完成基础设施的建设,支持互联网更好的发展,为人们提供更好的网路服务,才会使得更多的人进入网路,这样的良性循环的起因就是运营商在基础设施的大力投入。
同时,我们要知道,基础设施的投入成本非常高,且回报周期长,作为一般的私人企业是没有人愿意做的,因为它们的愿景是,投入成本低,回报周期短且要高,但是作为运营商,必须要干,为什么呢? 因为运营商是国企,国家要求运营商必须要做,从这里,我们也可以看出,近年来,国家对互联网的支持力度是非常大的。
我们可以看出,在整个网络中,运营商扮演的角色非常重要,可以说是网络的基石,也正因为运营商建设了基础设施,所以,用户的数据在传输过程中需要经过运营商的基础设施,换言之,运营商可以获得你的数据 (如果你是明文数据,甚至可以篡改信息)。
因为路由器可以构建局域网 (子网),而在一个子网中的IP我们称之为内网IP,或者私有IP,私有IP是局部的,可以在不同的子网内重复使用,因此这个特征就解决了IP不足的问题,这也是 IPv6 推展慢的原因之一,因为IPv4有解决IP地址不足的措施。
首先,对于家用路由器而言:
- 对内:它既可以构建一个子网;
- 对外:它又是上级网络的一个节点,这样的路由器可能会有很多级,最外层的运营商路由器,WAN口IP就是一个公网IP。
因此,也就绝对了路由器一定会有两套地址,LAN口IP和WAN口IP。
路由器是连接两个或多个网络的设备,通常用于将局域网(LAN)连接到广域网(WAN),或者连接到另一个局域网。在路由器上通常会有两种类型的网络接口:
WAN口(广域网口 --- Wide Area Network):这个接口用于连接到广域网,通常是当前网络的上级网络,给自己分配的IP地址;
LAN口(局域网口 --- Local Area Network):这个接口用于连接到局域网中的设备 (子网IP),LAN口负责在局域网内传输数据,并允许连接到路由器的设备相互通信和共享资源。
LAN口的IP地址,我们称之为子网IP (局域网IP);WAN口IP的地址,我们称之为外网IP。
数据是如何从私网到公网的,又如何从公网到私网的?
比如:
目的IP 122.77.241.3,源IP 192.168.1.201,直接将数据交付给家用路由器,由于网络号是前24位 (当前路由器的子网掩码是 255.255.255.0),即122.77.241.0,故目的主机肯定不在当前子网中,因此家用路由器直接将数据交付给运营商路由器,运营商路由器通过广域网在将数据交付给服务器,服务器收到数据,但当服务器准备构建响应时,出问题了,因为此时服务器收到的报文的IP地址是这样的:目的IP 122.77.241.3,源IP 192.168.1.201,这里的源IP竟然是一个私有IP,可是我们知道,私有IP不可以出现在公网中,此时服务器在构建响应时,就无法确定目的IP,因此上面这个过程是有问题的。
事实上,在每一次路由过程中,路由器会多做下面几件事情:
- 将IP报文中的源IP地址更新为当前路由器的WAN口IP;
- 每经过一个运营商的内网路由器 (家用路由器),都要做这个工作 (公网路由器不做)。
具体过程如下:
如上图所示,可以看到,服务器最后接受的IP报文中,源IP和目的IP都是公网IP;
子网内的主机需要和外网进行通信时,路由器会将IP首部中的源IP地址进行替换(替换成当前路由器的WAN口IP), 这样逐级替换,最终数据报中的源IP地址成为一个公网IP,这种技术称为NAT(Network Address Translation,网络地址转换);
此时服务器就可以构建响应,比如 [Dst: 122.77.241.4, Src: 122.77.241.3 数据];服务器就可以通过广域网将响应传输给运营商路由器,可是现在有一个问题,运营商路由器如何将数据发送给特定主机呢?
这个问题,我们只有到数据链路层中的ARP协议才能论述清楚。
如果我们希望自己实现的服务器,能够在公网上被访问到,就需要把服务器部署在一台具有外网IP的服务器上,这样的服务器可以在阿里云/腾讯云上进行购买。
8. 路由
数据在路由的过程中,就是这样一跳一跳 (类似 "问路") 的过程。
所谓的一跳就是数据链路层中的一个区间,具体在以太网中指从源MAC地址到达目的MAC地址之间的帧传输区间。
IP数据报在跨网络传输的过程中,途中是需要经过众多路由器的,这些路由器会判定IP数据报下一跳该去向哪里,那么路由器是如何判定的呢?
路由器是根据路由表来判定数据的下一跳位置,一般而言,路由器根据路由表得到的下一跳结果有三种:
- 路由器查询路由表后,得到了下一跳的具体位置;
- 路由器查询路由表后,没找到匹配的子网 (网络号),随后,路由器会将IP数据报转到默认路由 (default);
- 路由器查询路由表后,发现当前网络就是IP数据报中的目标网络,此时,路由器再将IP数据报转给目标主机。
本地主机也是工作在网络层的,比如云服务器,在云服务器中我们可以根据 route 查看当前主机的路由表,如下:
- Destination:目标网络,即数据报要传输到的目的地的网络;
- Gateway:网关,即数据包要经过的下一跳路由器的地址。当目的网络不在当前网络中时,数据包将被发送到网关,由网关进行转发;
- Genmask:子网掩码,用于指定网络地址中哪些部分是网络号,哪些部分是主机号;
- Flags:标志位,显示与该路由相关的一些标志属性,如 U (up-路由可用)、G (gateway-目标直接到达)、H (host-只适用于主机)、R (reinstate secondary路由恢复了) 等;
- Metric:路由的度量值,表示数据报传到目的地所要经过的跳数或路径的消耗,度量值越小表示更优先的路由;
- Ref:引用计数,表示该路由表目录被其他路由表目录引用的次数;
- Use:使用计数,表示该路由被使用的次数;
- Iface (Interface):网络接口,表示通过该接口发送IP数据报。
IP数据报的具体路由过程:
- 因为本地主机也是工作在网络层的,故转发IP数据报时,当前主机也会根据自身的路由表来判断这个IP数据报的目标网络是不是当前主机所在的网络,如果不是,再通过默认路由转发给家用路由器,如果目标网络是当前主机所在的网络,那么本地主机就会直接将数据报传递给目标主机,而不需要通过默认路由或家用路由器来转发;
- 当IP数据报到达路由器后,路由器就会根据IP数据报中的目的IP与当前路由表中的Genmask 进行按位与 ( '&' ) 操作,将得到的结果和 Destination 依次比较:
- 如果匹配成功,就代表这个IP数据报的下一跳地址就是当前的 Destination,并将数据通过相应的 Iface 网络接口发出;
- 如果将得到的结果和 Destination 依次比较,都没有匹配成功,那么就将这个IP数据报通过 default 默认路由对应的 Iface 网络接口发出, 一般情况下,默认路由 default 是当前网段中的另一台路由器;
- 当IP数据报随着上面的过程反复进行,IP数据报就会越来越靠近目标网络,最后到达目标网络时 (先找目标网络),当前路由器会根据IP数据报中的主机号锁定目标主机 (再找目标主机),最后将IP数据转发给目标主机,此时路由的过程就完成了。
路由表可以分为静态路由和动态路由:
- 静态路由是管理员手动配置的,包括目的地址、网关和接口等信息,不会自动更新;
- 动态路由则是由路由协议自动学习和更新的,根据网络拓扑、链路状态等动态信息自动计算路由表,实现网络动态路由的功能。
路由表的相关生成算法:距离向量算法、LS算法、Dijkstra算法等。