目录
网络层的主要工作就是:
1. 地址管理:对很多设备之间的地址进行管理。网络层中要从两个点之间找到一条具体的路径,就得先对路径的起点终点,和中间节点的地址管理起来,才能进行数据的传输;
2. 路由选择:也就是对两个节点之间的信息传输,进行路径规划。
IP协议报文结构
4位版本:指定IP协议的版本,此处的取值有IPv4和IPv6。(此处主要讲的是IPv4。)
4位首部长度:描述了IP报头多长(IP报头是可以变长的),因为在报头中有一个选项部分,是可有可无的。此处首部长度的单位也是 4 个字节,跟TCP报文类似。
8位服务类型:实际上只有4位有效。这4位中只有一位可以是1,其他都是0,4位就表示 IP协议的四种形态/四种工作模式:最小延时,最大吞吐量,最高可靠性,最小成本。(理解)
16位总长度:描述了一个 IP数据包的长度(头部+载荷),这个长度减去前面的 IP报头长度,剩下的就是载荷长度,一个完整的 TCP/UDP 数据报长度。
这是否就意味着一个IP数据报,最大只能传输64KB的数据了?确实是有这个限制的,但IP自身就支持对包的拆分和组装。一个IP数据报携带的数据载荷太长,超过了 64KB,就会在网络层针对数据进行拆分,把一个数据拆分成多个 IP数据报,再分别发送,然后接收方在进行重新拼接。
例如:
发送方:把100KB的数据,交给传输层(封装),传输层交给网络层(封装),网络层就把这个100KB的数据拆包成两份(比如是64KB+36KB),再把这两份交给数据链路层,由以太网封装成两个数据帧。(实际上,IP协议拆包不一定就按照64KB为单位进行拆分,实际的单位往往更小,往往取决于数据链路层的情况。)
接收方:数据链路层,针对两个数据帧进行分用,得到两个IP数据报,交给网络层,网络层针对这两个IP数据报进行解析,把里面的载荷拼成一个,再交给传输层。
这三位就是为了实现拆包,所引入的一些辅助机制。
16位标识:同一份数据拆成的多个包标识是一样的;
3位标志:表示的是结束标识;
13位片偏移:标识了多个包的先后顺序。(解决先发后至问题)
8位生存时间:标识一个数据报在网络上能够传输的最大时间。这个时间的单位不是"秒",而是"次数"。一个数据报构造出来,都会有一个初始的生存时间数值,这个数据报每经过一次路由器转发,就减一。如果一直减到0,还没有达到目标,此时就认为这个包永远都到不了了,就可以丢弃了。
8位协议:描述了当前载荷部分是属于哪个协议的。(TCP,UDP或者其他协议)
16位首部校验和:此处只需要针对首部进行校验,因为载荷部分(TCP/UDP数据报或其他)自身已经有校验和了。 如果发现校验和不一致,就会直接丢弃,IP不负责重传,如果上层使用的是TCP,TCP会在没有收到ack的时候进行重传。
32位源IP地址和32位目的IP地址是 IP协议中最重要的部分!!!
此处看到的是32位,但在日常中看到的一般都是 127.0.0.1 这种点分十进制的形式,使用三个 . 把32位,4个字节的数字给分隔开,分成4个部分,每个部分分别使用 0-255 十进制整数表示。
32位数字,可以标识42亿九千万..个数字,但是期望使用这个表示全世界所有的上网设备(手机+pc+服务器+路由器+各自网络设备...),在当今世界,显然是不现实的。
网络地址管理
方案1. 动态分配IP地址
1. 动态分配IP地址,在设备没上线的时候,把该设备的IP地址分配给另一个上线的设备,此时就可以省下一批IP地址了。但这个方案没有从根本上增加 IP地址,只是提高了利用率,治标不治本。
方案2. NAT网络地址转换
2. NAT网络地址转换。本质上是使用一个IP代表一批设备。然后在一批设备中,通过端口号来进行区分。
在NAT背景下,就把 IP地址分为两个大类。
1. 内网IP(私网IP):10.* ,172.16.* - 172.31.* ,192.168.* ;
通过cmd,ipconfig可以看到自己电脑的IP。可以观察到,电脑上的IP地址基本上都是属于局域网内部的私网IP形式。
2. 外网IP(公网IP) :剩下的就都是外网IP了;
NAT要求,外网IP 必须是唯一的,内网IP可以在不同的局域网中重复出现。如果某个内网里的设备想访问外网的设备,就需要对应的NAT设备(路由器) ,把IP地址进行映射,从而完成网络访问。反之,外网的设备,是无法直接访问内网的设备的,不同局域网的内网的设备无法直接相互访问。
内网设备访问外网服务器的过程:
此时,只要我们的内网设备是经过运营商路由器转发给服务器,服务器看到的源IP就都一样,如果是多台设备同时访问同一个服务器,服务器的响应就会先发送给路由器,路由器再根据这些设备不同的端口号来进行区分,决定发给哪个设备。(此处的端口指的是传输层的端口号的端口)
因此,服务器能拿到的只是路由器的IP,而不能拿到我设备的内网IP。如果我的设备不主动和服务器进行联系,服务器也就不会知道我的设备的端口号,从而无法主动找到我的设备。
NAT机制能够有效的解决IP不够用的问题,但是带来的副作用就是网络环境更加复杂了。
方案3. 使用IPv6
3. IPv6:这个是从根本上来解决IP不够用的问题。
使用16个字节来表示 IP地址。
16个字节表示的地址数:42亿*42亿*42亿*42亿,这也就是一个天文数字了,对于当今的所有设备,一个设备一个IP显然是绰绰有余的。
IPv6看起来很美好,但是如今世界上,仍然是以 NAT+IPv4+动态分配来进行网络组建的,真正使用到IPv6还是相对比较少的。 (但是目前国内的IPv6普及度是很高的!)
这里也推荐给大家一个很有意义,有关中国IPv6普及的视频:电子监听、全国断网,棱镜门背后,中国如何从末路狂奔到世界之巅_哔哩哔哩_bilibili
网络号和主机号
IP地址分为两个部分:网络号+主机号
网络号:标识网段,保证相互连接的两个网段具有不同的标识;
主机号:标识主机,同一网段内,主机之间具有相同的网络号,但是必须有不同的主机号;
例如一个常见的设定:192.168.1.2 ;网络号是192.168.1;主机号就是 2;
且当前的局域网下的设备,网络号就都是192.168.1,主机号是不同的!!!
如果局域网里的主机号相同,就没法上网了。
一个典型的局域网环境:(路由器一般都是有两个IP,分别属于不同的网段的,功能就是将两个局域网连接到一起)
子网掩码
一个IP地址,前面从哪到哪是网络号,后面从哪到哪是主机号,分界是怎么定的,这也就引出一个单独的概念:子网掩码。
子网掩码格式和 IP 地址一样,也是一个 32 位的二进制数。其中左边是网络位,用二进制数字 “1” 表示, 1的数目等于网络位的长度;右边是主机位,用二进制数字“0” 表示, 0 的数目等于主机位的长度。也可以通过cmd,ipconfig来查看
常见的子网掩码:255.255.255.0 => 1111 1111 1111 1111 1111 1111 0000 0000 因此255.255.255就表示网络号;0就表示主机号;
将IP地址中的主机地址全部设为0,就成为了网络号,代表这个局域网;
将IP地址中的主机地址全部设为1,就成为了广播地址,用于给同一个链路中相互连接的所有主机发送数据包;例如:192.168.0.255的主机地址为255,此时使用UDP往这个地址上发数据报,整个局域网所有设备都能够接收到。(UDP是天然支持广播的)127.*的IP地址用于本机环回(loop back)测试,通常是127.0.0.1本机环回主要用于本机到本机的网络通信(系统内部为了性能,不会走网络的方式传输),对于开发网络通信的程序(即网络编程)而言,常见的开发方式都是本机到本机的网络通信。主机号为1,例如192.168.0.1,通常是"网关IP"
路由选择
IP协议还有一个重要的功能:路由选择。
由于其复杂性,这里只是简单介绍。
路由选择就是路径规划,但是由于网络环境的复杂性,任何一个节点(路由器)都是无法感知到网络环境的全貌的,因此路由选择的核心思路就是 "问路"。每个路由器都会保存一定的周围设备的信息(路由表),每次有一个IP数据报经过路由器,就需要匹配路由表,看看接下来应该怎么传输。如果路由表上有匹配的项,就会直接按照要求的走就行,如果没有匹配的项,就会提供一个默认路径。每经过一个节点,生存时间就会减一,如果减到0了,还没有到,就说明这个包永远也到不了,就会被丢弃了。
对于路由选择,这只是和简单的描述,实际上是更加复杂的。