📚相关专栏:计算机网络那些事
前几篇文章中我们深入研究了TCP协议,因为TCP协议在我们日常开发中的使用频率非常高。而相比之下,IP协议与我们普通程序员关系就没那么近了。一般是专门开发网络设备的程序员(开发路由器、交换机、防火墙)才会用到。不过,了解IP协议的构成与性质业可以加深我们对网络传输的理解,一定程度上能提高我们的认知,因此还是有必要学习一下的
一、初识IP协议
IP协议主要作用:
1、地址管理 ===> IP地址
2、路由选择 ===> 对数据传输的路径进行规划
- 主机: 配有IP地址, 但是不进⾏路由控制的设备
- 路由器: 即配有IP地址, ⼜能进⾏路由控制
- 节点: 主机和路由器的统称
协议头格式:
4位版本
实际上只有两个取值:
4 ==> IPv4
6 ==>IPv6
4位首部长度
IP协议的报头与TCP类似,也是变长的
注意:这里的一位代表着四个字节
4位首部长度的表示范围:0=>15
- 则其表示的实际报文长度范围:0=>60字节
8位服务类型
服务类型(TOS),即 "type of service"
3位优先权字段(已经弃⽤),4位TOS字段,和1位保留字段(必须置为0)
4位TOS分别表⽰:
- 最⼩延时:数据从 A 到 B 的时间消耗最短
- 最⼤吞吐量:数据从 A 到 B 单位时间内,传输的数据更多
- 最⾼可靠性:一定程度上降低丢包的概率(IP协议并不像TCP那样有严格的可靠性)
- 最⼩成本:设备上消耗的资源较少
注意: 这四者相互冲突,只能选择⼀个
16位总长度
表示IP数据报的长度。
与UDP协议一样也是16 位(2个字节),因此单个数据报最多只能传 64 KB的数据。但这并不是IP协议传输的极限。
IP协议有专门的拆包组包机制:当需要传输 64 KB以上的数据时,会自动把大的数据包,拆分成多个 IP 数据报携带传输,传输到接收方后再进行拼接。
16位标识、3位标志、13位片偏移
IP协议会自动拆包,同一个载荷的数据会被拆分成多份,交给多个 IP 数据报来携带。
- 16 位标识
这多个 IP 数据报是相同的值,表示这些数据报是同一组的。
- 13 位片偏移
决定组包时该数据报的位置。因为网络传输中存在"后发先至"问题,不能直接根据接收顺序进行组包
- 3 位标志位
只有两个有效位。(剩下一个保留位)
- 一个表示当前这个包是否需要组包(是否是拆包的一部分)
- 另一个表示当前包是否为组包中的最后一个包(确认组包是否结束)
8 位生存时间(TTL)
表示一个数据包在网络中最多存活多长的时间
假如在构造一个 IP 数据报时,目的 IP 写错了,写成不存在的 IP 了,如果不加以限制,这样的数据报就会无限地传输下去,会浪费许多网络资源。而通过 TTL 就约定了传输的上限,达到上限时,数据报就会被自动丢弃掉。
- TTL 的单位不是 s 或 min ,而是"次数",指经过路由器转发的次数
当发送一个数据报时,会设置一个初始的 TTL 值(32,64,128等),数据报每经过一个路由器转发,TTL 就会 -1 (经过交换机并不会减少),一旦TTL减至 0,该数据报就会被路由器直接丢弃。
可以通过 ping 命令来检测网络的联通性:
输入上述命令,就会向bilibili发送一个数据包,然后bilibili会返回一个响应。
该数据包初始 TTL 为64,而返回的 TTL 为56,说明传输中经过了 8 个数据包的转发,最终到达了b站
TTL 初始值设为 64 够用吗?
正常情况下,是非常充裕的。社会学中对此有专门的"六度空间"理论
并且在发送数据包时,还能将 TTL 设为128。因此一般不用担心TTL会不够用
8 位协议
记录 IP数据包中携带的载荷的传输层协议。
- 即通过这里的记录,来告诉接收端该用 TCP 、UDP还是其它协议去解析数据。保证数据解析的准确性。
类似于 TCP/IP 报头中的"端口号"作用就是决定要将数据交给哪个应用程序,这里协议的记录就是为了决定要将数据交给哪个传输层协议进行解析
16 位首部校验和
验证数据在传输中是否出错(只针对首部,即IP报头)
因为载荷部分会由 TCP/IP 协议通过其校验和进行校验。
32 位源 IP 地址、32 位目的 IP 地址
这是IP数据报中最关键的信息,记录了数据包的起始地与目的地。
可以通过 ipconfig 命令查看本机的IP地址:
IP 地址是32位的整数, 不太方便让人直接阅读,通常会采用 "点分十进制" 的表示方法,即把 32 位 IP地址通过 "." 号每 8 位一组分为 4 组,这样每组就是一个字节,范围是0-255。
因此 IP地址的表示范围就可以为 "0.0.0.0" 到 **"255.255.255.255"**了。
二、地址管理
1、地址分配
IP 地址,是用来标识网络上的某一个设备,相当于互联网中的 "身份证"。这样,我们当然希望每个设备的 IP 地址都是唯一的。这样在网络通信中就能更方便地找到每一个设备了。
而上文中我们谈到,IP 地址是 32 位的整数。而 32 位表示的数据范围是 "0=>42亿9千万"。
这个数字放在几十年前 IPv4 刚提出时还是个天文数字。那时候能网络上的设备数是远远达不到这个数字的,可以说绰绰有余。
但是在信息化高度发展的今天,不用说几乎人手一部的手机了,汽车、冰箱、手表、空调......等等,恨不得啥玩意都给你连个网。如今在在互联网上活跃的设备数已经远远超过 42亿9千万 了。
类似的问题在 UDP 协议中也出现过。那么 IP协议是如何应对这一问题的呢?我们接着往下看
1、动态分配 IP 地址
一个设备上网就分配 IP,不上网就不分配。这样,只要同时上网的设备数不超过 42亿9千万,就勉强还能应对了
不过这种方法治标不治本,还是不能从根本上解决问题。
2、NAT 网络地址转换
以一当千,通过一个 IP 代表一大波设备
将 IP地址分为两大类:
- 内网IP/私网IP
- 外网IP/公网IP
要求公网 IP必须是唯一的,但是私网 IP在不同的局域网中是允许重复的
这样运营商的公网 IP,不是服务一个设备,而是服务一个片区,可能有上万个设备。此时一个 IP 就代表了上万个设备,此时 IP 的利用率就大大提高了。
至于NAT的具体地址分配机制,博主之后会专门写一篇文章介绍
3、IPv6 协议
从根本上解决了 IP 地址不够用的问题。
- IPv4通过 32 位 4个字节表示 IP地址
- IPv6则通过 128位 16个字节表示 IP地址
注意,这提升的可不止是 4倍。这里每一位的提升都是指数关系。
4个字节能表示最多 ,而16个字节最多可以表示 ,相当于 ***。什么概念呢?它可以做到给地球上的每一粒沙子都分配一个唯一的地址。
- IPv6 那么好用,为什么现在还没有代替IPv4呢?
因为其提出的时间在上世纪 90 年代,时间上与 NAT 差不多。之所以 IPv6 推广举步维艰,就是因为 IPv6 与 IPv4 并不兼容。
- 如果要使用 IPv6 就需要更换新的设备,成本是比较高的
- NAT 机制只需要给路由器设备更新升级软件就行了,不需要更换硬件。相比之下成本就低很多了
不过,目前 IPv6 在国内的普及率已经非常高了,超过 70%了。
2、网段划分
目前流行的划分方式是CIDR(Classless Interdomain Routing)
将 IP地址分为两个部分, ⽹络号和主机号
- 左半部分:⽹络号
- 右半部分:主机号
需要通过 "子网掩码" 区分出网络号与主机号。
子网掩码也是 32 位整数,左半部分全是 1,右半部分全是 0;
- 比如这里的**"255.255.255.0"** 就是 "11111111.11111111.11111111.00000000"
- 所以上图中网络号就是 "192.168.100" ,主机号就是 "152"
还有一种更简洁的表示方式,如140.252.20.68/24,表⽰IP地址为140.252.20.68, ⼦⽹掩码的⾼24位是1,也就是255.255.255.0
网络中规定:
- 同一个局域网中的设备,网络号必须相同,主机号必须不同
在这个局域网中:
某个设备号不相同的话,就无法上网
某个设备的网络号虽然相同,但主机号和别的设备重复,也无法上网
路由器上有两种网络接口:
- LAN口
- WAN口
- LAN口接局域网内的设备
- WAN口接上层路由器
这里的路由器1就负责连接了两个局域网。这两个局域网就被称之为相邻局域网,IP地址的网络号就必须不同。如果相邻局域网网络号出现重复,就会导致无法正常上网。
3、特殊的 IP地址
1、主机号为全 0
此时这个IP就表示当前网段(相当于网络号)
注意:给局域网中的设备分配 IP地址时,不能把主机号设为全0
2、主机号全 1
⼴播地址,⽤于给同⼀个链路中相互连接的所有主机发送数据包
一般会在手机投屏时使用:
手机上点击投屏按钮后,就会往对应的广播 IP上发一个 UDP数据包。
- 收到这个数据包的设备不具备投屏功能,就不会做出反应
- 收到这个数据包的设备具备投屏功能,就会返回一个响应,告诉手机自己的信息(如IP地址等)
3、127.* 环回IP(loopback)
- 自发自收:给这个IP发数据,这个IP就会发一个相同的数据返回给该设备,相当于自己发给自己
一般使用环回IP进行测试。虽然我们写的网络程序一般都是要跨主机通信的。但是在代码研发阶段,往往需要在本机上自行测试。使用环回IP就能用一台主机模拟客户端与服务端的通信交互
一般使用的环回IP为 127.0.0.1
三、路由选择
网络是复杂的网状结构,从一个节点到另一个节点之间,可能会存在很多条路线。
就像现实中复杂的交通网络一般。当我们打开手机上的地图软件时,输入一个目的地,就会提供出多条线路供我们选择。
不过地图软件的路由选择与IP协议的路由选择是有本质区别的:
- **地图软件:**能够知道路线的全貌
从总体上规划出 "最优路线"(用时最短、成本最低、最少换乘)
- **路由器:**无法知道整个网络结构的全貌。只能知道其中的一小部分(每个路由器只知道其附近的设备的情况)
无法得到 "最优路线",只能得到 "较优路线"
每个路由器都会维护一个路由表(类似于hash表):
- key 就相当于 IP地址(网络号)
- value 就是对应的网络接口(往哪个方向走)
这个路由表并不会记录网络中所有线路的信息,但是会记录与他相邻的一片区域的线路信息。
当 IP数据报到达路由器时,就会进行查表操作,判断IP数据报中的目的IP在路由表中是否存在。
- 如果存在,则继续按照路由表指向的方向继续转发即可
- 如果不存在,则会触发"默认的表项",将数据报转发至更高层级的路由(认识的设备范围更广)
这样一级一级往上传,遇到认识目的 IP的路由器的概率就更高,最终成功找到目标路线,将数据报送达目的地
那么本篇文章就到此为止了,如果觉得这篇文章对你有帮助的话,可以点一下关注和点赞来支持作者哦。如果有什么讲的不对的地方欢迎在评论区指出,希望能够和你们一起进步✊