【计算机网络】网络层
网络层基于数据链路层实现,实现了主机到主机的通信,这一章对其中常见的知识进行讲解
概览&目标
网络层在五层模型中的位置
数据链路层的通信协议,能够让多台设备共享同一条物理信道。交换机在数据链路层中提供了转发的功能,与只使用一根网线串联起所有设备的网络相比,含有交换机的网络更具有可拓展性。交换机的转发功能,是通过维护当前网络中Mac地址
与端口号
的映射关系实现的,网络中的设备数受到交换机的存储能力的限制。因此**:数据链路层的传输范围有限**。
网络层的引入,将大的网络划分为了不同的子网,数据链路层只需要关心在某一子网内的数据传输问题即可,这和分治的思想非常相似。
如上图所示,两个路由器将网络划分为三个部分,紫色的交换机只需要关心如何在紫色的网络中进行数据传输即可,具体的原因我们后面再讲。网络层设备也无需关心数据链路层的具体情况,只需要在网络层构建的虚拟信道中进行通信即可。
需要学习的内容
如何标识网络层中的设备?
Mac地址是数据链路层设备的唯一标识,网络层设备也需要一个地址进行区分。
知道目标设备的标识,如何在众多网络中找到对方?
如何通过网络层信息知道对方的MAC地址?
IP数据报(v4)
基础信息
- 源IP地址 & 目标IP地址:网络层将数据从一台主机传送到另一台主机,数据报中存储双方地址进行标记,每个地址长32位;
- 总长度:记录IP数据报头部+数据部分的长度,单位是
byte
; - 首部长度:记录IP数据报头部长度,单位是
4 bytes
。这样设计是因为ip数据包的头部长度必须是4 bytes
的整数倍,就算是对头部进行拓展时也需要通过补0的方法来维护这一性质; - 生存时间(TTL):从源主机传送到目标主机的过程中能够经过的最大路由数量。路由器每次转发之前都会将TTL减1,如果发现TTL为0就会直接丢弃;
- 头部检验和:使用checksum作为检验和,只检验头部数据的正确性;
IP数据报分片
每个网络能够支持的最大数据报长度不同,我们将网络中的IP
数据报中能够承载的数据部分长度叫做MTU
。当路由设备识别到转发的数据报大小大于MTU
时,有两种策略:
- 扔掉这个数据报(直接不处理了,摆烂);
- 将数据报分片,再由接收方进行拼接;
接下来从数据报格式的角度来理解一下这个过程。
我们依次讲解:
DF(Don't Fragment)
:为0时表示允许分片,其他分片相关标识位有效。为1时表示禁止分片,其他分片相关标识全都无效;后面的字段,我们只讨论
DF
为0,即允许分片时的意义;另外,DF为0时数据不一定被分片。MF(More Fragmentation)
:为1时表示后面还有更多分片,即当前分片不是最后一片;为0时表示没有更多分片了,当前分片可能是最后一片,也可能数据报根本没有被分片;分片标识:相当于分片的ID,和目的IP、源IP配合唯一标识一组分片;
片偏移:标识当前片的数据的起始地址在总体中的偏移量。
片偏移的单位是8byte,这是因为总长度用了
16bit
,而片偏移只用了13bit
,因此将片偏移后补3个0,让他能够表达16bit
的内容。不过也正因如此,除最后一个分片外,其他分片的长度必须为8byte
的整数倍;
ip数据报分片实例
在这里,我们只关注分片相关的标识位以及数据部分的长度。假设网络的MTU = 1500Byte
,这时传入了一个数据部分长度为4000Byte
的ip数据报。
传入的数据ID
为X
,DF
为0,表示允许分片。他的长度大于MTU
,需要被分片。
$$
4000 / 1500 = 2.6666…
$$
因此,会被分为三片,前两片中的数据部分长度与MTU
相同,最后一片有剩余的数据。
IP地址
网络号与主机号
通过ip
数据报的格式可以看出ip
地址是一个32位数字。为了更好的供人类观看,我们将他的每一个字节用整数表示出来,中间用点分割。如:192.168.0.1
。那么在实际的网络中ip地址
对设备进行分层描述:第一部分是网络号,表示所在网络的编号;第二部分是设备号,表示设备在该网络中的编号。
子网掩码
不同子网中的主机数量未必相同,因此有了子网掩码。子网掩码用于记录网络号在ip
地址中占高几位,如:
IP
地址为192.168.43.56
- 子网掩码为
255.255.0.0
子网掩码与IP
地址的长度相同,子网掩码中为1
的位,在IP
地址中表示网络号;为0的位则表示主机号。在上面的例子中,该ip
地址对应的网络号为192.168.43.56
。
正是子网掩码实现了网络层次的划分,如:
ip地址 | 子网掩码 | 网络号 |
---|---|---|
192.168.0.1 | 255.255.0.0 | 192.168.0.0 |
192.168.3.127 | 255.255.255.0 | 192.168.3.0 |
192.168.3.188 | 255.255.255.0 | 192.168.3.0 |
192.168.4.134 | 255.255.255.0 | 192.168.4.0 |
在上述网络中,网络被分为两层,这些机器同属于192.168.0.0
这个子网,在子网中,又进行了进一步的细分,分为192.168.3.0
,192.168.4.0
两个子网。子网下有不同的设备,整体结构如下图所示。
新的问题又产生了:想要将数据报从当前子网发出,应该怎么发?
网关
实际上,子网192.168.3.0
中的设备在向外部进行通信时,不会直接发出。在该网络中,会存在一个"代表",他负责收集子网中的数据报向外发送;也负责接收外部请求,向内分发;这个网关就是一个入口。
假如192.168.3.127
想要发送数据到192.168.4.134
;子网192.168.3.0
的网关为192.168.3.1
;子网192.168.4.0
的网关为192.168.4.1
。
那么:
192.168.3.127
监测到目标地址不在当前子网中,会将数据发送给他的网关192.168.3.1
;192.168.3.1
同时处于192.168.3.0
和192.168.0.0
两个网络中,他监测到目标在192.168.0.0
子网中,所以不把数据发送给自己的网关, 而是直接在子网内发送给192.168.4.1
即192.168.4.0
网络的网关;192.168.4.1
收到数据报,监测到目标在192.168.4.0
网络中,直接发送给192.168.4.134
;
子网内传输ARP
我想要发一个包到子网内的设备,我们的数据在网络层封装成数据报后需要交给链路层进行发送。数据链路层需要我们指定目标的MAC
地址,这要怎么解决呢?
实际上每个参与到网络层的设备中都会维护一个ARP
表,其中记录了子网中IP
地址与MAC
地址的映射关系。可以通过arp -a
对arp表进行查看,具体如下:
DHCP——IP地址分配技术
经过上面的学习,我们发现,如果一台机器想要正常上网,需要配置:
IP
地址:网络号要与所在网络相同,设备号不能与当前子网中其他设备重复;- 子网掩码:子网掩码必须和网络号相互配合;
- 网关:必须显式的制定当前子网的代理人;
这些参数显然不能让每一个用户去手工配置,因此就有了DHCP
,他的目的就是让用户不去手工配置这些参数,而是在连入网络时自动配置。现代的路由器上一般都会维护一个小型的DHCP
服务器,整体过程如下。
但是值得注意的是,DHCP
算得上是一个应用层协议,他是借助UDP
协议实现的。
除此之外,分配地址后,客户端需要定期向DHCPServer
进行续租操作,否则IP
地址会被收回,并且分配给其他设备使用。
数据跨子网传输
NAT网络地址转换
上一小节中讲到每个子网中会有一个“代理人”网关,他同时存在于两个网络中,负责收集子网的数据向外发送,假设有下图中的网络。
现在路由器代理的内网中有多台设备,他们都需要向外网发送数据、接收数据。如果路由不对数据报进行任何处理,在发送时候不会有任何影响。但是在接受数据报时,接收的对象是子网内ip地址,无法在公网找到当前路由。NAT
技术通过映射端口号的方法来满足跨网通信。
简谈传输层
在了解NAT
前需要先了解一点传输层知识,网络层实现了复杂网络中从一台主机到另一台主机的通信。但实际应用过程中,需要进行进程与进程之间通信,所以传输层在网络层基础上进一步封装,实现进程间通信。具体讲:
- 网络层中定义了端口号;
- 应用进程会监听当前主机的某个端口;
- 不同进程监听不同端口,同一个端口在一般情况下不可以被多个进程监听;
在传输层指定端口就可以达到进程间通信的目的。
回到NAT协议
NAT
协议较为特殊,他通过映射端口号来实现代理。路由接收到子网中设备的数据报,其中:
- 网络层协议中会带有发送方的IP地址;
- 传输层协议中会带有发送方的端口号;
路由开辟一个新的端口用于代理收到的IP, port
,路由中维护一个NAT
表,记录自身端口号与子网中IP, port
的映射关系。当路由收到数据后会检查数据的端口号,在NAT
表中查找端口号对应的IP, port
,随后替换数据报中的IP
为NAT
表中的IP
,随后将数据部分承载的上层协议的Port
也进行替换。
CIDR——路由聚合
上面我们讲解了IP
地址,想要解读一个IP
地址需要知道他的IP
地址,以及他的子网掩码。
有类IP地址
有组织制定了标准,在该标准中,将IP
地址划分为5类:
A类
:0.0.0.0 ~ 126.255.255.255
这个范围被称为A类
,它的子网掩码为255.0.0.0
;B类
:127.0.0.0 ~ 191.255.255.255
这个范围被称为B类
,它的子网掩码为255.255.0.0
;- …
- 以此类推
我们不详细介绍有类IP了,有类IP的划分过于固定,难以适应现实世界的情况;
CIDR
CIDR
解决了有类IP
划分过于固定的问题,具体来说CIDR
使用下面的方法表示一个IP地址
:
192.168.3.4/24
这里就表示:
IP
地址为:192.168.3.4
- 子网掩码为:
255.255.255.0
后缀可以任意活动,这样就可以针对不同的情况进行更好的划分。
路由聚合
实际上,在每个路由中都会维护一个转发表。假设有这样一个网络:
目标地址 | 转发到哪个子网 |
---|---|
192.168.3.1 | A |
192.168.4.X | B |
但是,实际情况可能有所不同,如:
这个时候就会触发路由聚合。
目标地址 | 转发到哪个子网 |
---|---|
192.168.4.3 | A |
192.168.4.0 | B |
192.168.5.2 | B |
在实际转发过程中,将在路由表中对目标地址进行最长前缀匹配,将数据报转发到最长匹配的目标中。