计算机网络 Chap.4 网络层
本系列计算机网络博文基于Bilibili王道的免费考研课程整理而来, 目的在于系统的梳理计算机专业课的基础知识, 并为将来的面试做好充分的准备.
除本系列外, 计算机考研相关还包括数据结构 / 操作系统 / 计算机组成原理的相关内容.
4.1 网络层的功能
老图了, 每章开始都得拿出来哈.
网络层, 其为 传输层 提供服务, 将传输层的数据封装为 IP数据报(也叫分组) , 网络中的路由器根据数据报首部中的源和目的IP地址来进行 分组转发 . 其能够实现 主机到主机的传输 .
网络层需要实现的功能主要分以下三个部分:
- 异构网络互联
- 异构网络: 不同网络展现出来的拓扑结构不同, 主机类型也不相同. 这种不同的网络被称为异构网络.
- 路由器(在TCP / IP体系中也叫 网关 )是其中的重要部分.
- 路由与转发
- 路由: 各个路由器相互配合, 规划一个IP数据报的最佳转发路径(通过 路由表 进行)
- 转发: 根据自己的 转发表 来将收到的IP数据报通过合适的接口转发出去
- 拥塞控制
- 拥塞: 网络上的分组过多, 超负荷导致的网络性能下降
- 拥塞控制的方法通常分两种:
- 开环控制: 提前设计, 网络开启后不再更改
- 闭环控制: 动态监视拥塞状况, 将拥塞状况及时防窥给路由器, 路由器实时调整路由表
4.2 IP协议
IP是网络层中某个主机的标识符, 网络层需要实现主机到主机的传播, 其首先必然需要明确收发地对吧, IP地址就是干这个事情的.
4.2.1 IPv4及其分组
Ipv4的地址是一个32位的比特串, 人们为了方便记忆, 将其每八位看作为一组, 共四组.
因此我们通常IP是用三个点分隔开来的, 同时每个字部分的取值范围是 $ 0 \sim 2^{8}-1 $
我们得把这玩意拆开来看看:
- 首部
- 固定首部(一定会有这20B)
- 版本: 使用的协议版本, 当前只有v4和v6
- 首部长度: 首部的总长度, 以 4B 为单位
- 区分服务: 不重要, 跳过它
- 总长度: 整个IP数据报的长度, 以1B为单位
- 分片相关的三个字段:
- 分片: 当一个Ipv4帧超过了下一段链路能承载的最大帧长(MTU, Maximum Transfer Unit)限制时, 就会进行分片.
- 标识: 通常由发送方源主机生成, 是一个自增序列, 用于让接收方区分收到的不同分片来自于哪个源主机的哪个IP数据报
- 标志: 共3bit
- 最低位MF(More Fragment): 本分片后是否还有更多分片
- 居中位DF(Don’t Fragment): 本数据报不允许分片
- 最高位不管, 没用
- 片偏移: 在分片前, 本分片的数据部分在原IP数据报中的位置, 以8B为单位
- 生存时间(TTL, Time to Live): 一个IP数据报能在网络上经过的最大节点数目
- 协议: 标识上层传输层使用的协议
- 首部校验和: 只校验首部是否正确, 数据部分我不管(如果这一部分全零则代表首部都不用校验)
- 源地址 / 目的地址: 不用再赘述了哈
- 可变部分
- 可选字段
- 填充(为了保证首部长度是4B的整数倍, 与首部长度字段对应)
- 固定首部(一定会有这20B)
- 数据部分(从上层传输层过来的报文)
注意
通过对分片的理解, 我们得知了, 分片这个动作时能够在源主机 / 路由器中任何一个节点进行的, 但重组这个动作只能在目的主机中进行.同时, 除了最后一个分片外, 其余分片数据部分的大小也必定是8B的整数倍.
4.3 IP地址及其分组
这一节会涉及到IPv4地址的分组以及其发展历程, 这二者是息息相关的.
4.3.1 最初的IP地址设计: ABCDE
我们先看一下IPv4地址的容量, 我们此前说过Ipv4地址共32bit, 换算成十进制即:
$ 2^{32} \approx 42亿 $
这就出问题了, 如果按照最初设计的设想(1981年), 为每个电子设备以及每个路由器的接口都分配一个唯一的ip, 那显然, 42亿有点太少了. 但在那个年代来看, 这个容量应该是绝对够用的.
当时的IP地址总分配管理者为 ICANN(互联网名字和数字分配机构) . 它们将IP分为了五类:
- A: 1 ~ 126
- B: 128 ~ 191
- C: 192 ~ 223
- D: 224 ~ 239
- E: 240 ~ 255
其中, ABC为单播地址, D为多播地址, E类保留至今后使用.
这里划分的规则用二进制来看还是很明确的, A类地址以0开头, B以10开头, C以110开头, D以1110开头, E以1111开头.
概念: 多播地址
相当于通过一个IPv4地址映射多个单播地址.(类似于一个群组号, 向这个群组中发送消息, 则群组内的所有主机都能收到这条消息)
需要注意的是, IPv4地址在当时定了个规则, 即 <网络号> + <主机号> 的双重结构. 网络号通常意味着 一个子网 , 主机号则负责标注该子网下的某一台特定主机.
我们通过一张图引入几个概念, 并向读者理清楚IP分组到底是怎么发送到指定的另一个主机的:
- IP转发表: 是每一个路由器均有的一张表, 它负责在路由器接收到IP数据报时进行从上至下的筛选, 直到筛选到符合的表项后向指定端口进行转发(简单而言就是判断这个IP该往我的哪个端口转发)
- ARP协议: 是一种通过目的IP以及特定查询报文来确定其IP所对应的MAC地址的协议, 它只能在同一子网内生效.
- 首先, 一台计算机进入接入互联网中的某一个子网, 一定会被分配到该子网下属的一个主机号, 并被告知一个默认的网关(即需要跨子网通信时必定要经过的一个路由器, 也就是该子网的边缘路由器)
- 随后, 该主机希望向自己子网外的某个子网发送数据, 则先将目的IP与自己的本机IP填入分组中, 传递给下层数据链路层.
- 接下来进行组帧, 重点是目的MAC地址的填写, 也涉及到了第一次分类, 是关于目的IP相对自己的位置而言的:
- 如果目的IP与自己处于同一个子网, 则直接通过ARP协议找到其MAC地址并填入.
- 如果目的IP与自己不在同一个子网, 则通过ARP协议先找到自己默认网关的MAC地址并填入
- 接下来就是接收方的分类:
- 同一子网的主机直接收到了该数据报, 传输结束.(都不用走路由转发)
- 网关路由器收到该帧, 拆帧并向上传输给网络层后, 网络层会检测目的IP地址与哪一个接口相匹配(通过IP转发表), 并在下一次组帧时将目的MAC地址更改为其传送目标路由器的MAC地址(同样通过ARP协议).
- 到了下一个结点, 重复这一过程(3~4), 直到该数据报转发到了目标主机为止.
这整个过程其实不是非常难理解, 但是涉及到了两个问题:
- ARP协议怎么拿到MAC的?
- IP转发表怎么形成的?
但在这里, 我们暂且按下不表, 还请读者带着这两个问题读下去.
除了上述的分类之外, 最初的IP设计还给出了几个特殊地址:
我们假设 IP地址: <网络号Y> + <主机号X>
- X全0代表着子网本身, 不能被分配给网络内的任何一个主机, 也不能作为目的地址以及源地址.(比如上图中的166.1.0.0)
- X全1代表着给这个子网 广播 该分组, 只能作为目的地址使用
- Y全0代表着 本子网中的指定主机 , 只能作为源地址使用
- Y, X均全0代表着 本子网上的本主机 , 在DHCP协议中有应用, 只能作为源地址来使用
- Y, X均全1代表着 向本子网中的全部主机广播该分组 , 只能作为目的地址使用
- Y = 127: 环回自检地址, 代表自己这台主机本身, 用于本地软件的测试.(不信读者回去看看地址分类是不是没有127)
第四条和第五条通常在一个主机刚刚接入网络, 还没有被分配IP地址时使用. 其会发送一条DHCP报文, 源地址为 0.0.0.0(全0), 目的地址为 255.255.255.255(全1), 用于向本子网中的DHCP服务器获取IP地址. 具体的内容会在DHCP协议中详细叙述.
4.3.2 子网划分和子网掩码
看到了前面一小节ICANN的划分方式, 相信很多读者已经有点想法了, 哎, 我又没有那么多机子, 我能不能再把ip地址进一步划分呢?
那答案当然是可以的.
上图中, 以B类地址为例, 一个学校将原本分配给它的一个B类地址划分成了更细的两个子网: 166.1.0.x ~ 166.1.127.x 以及 166.1.128.x ~ 166.1.255.x, 其实本质上, 就是将后面原本16个主机字段, 单独分出来一个来额外标识子网号.
通过上述例子, 我们能知道, 引入了子网后, IP地址的结构发生了一点点变化:
<网络号> + <子网号> + <主机号>
哎这好像很简单啊? 还有啥能说的?
读者千万不要忘了, 我们上一节说过的IP数据报传输过程.
我们知道, IP数据报传输需要首先判断目的IP到底在不在我的这个子网中, 如果在我的子网中, 我就不用走路由, 直接填它的MAC转发过去即可对不对.
那现在子网划分技术出现了, 从好的方面讲, 这使得某个机构或公司能够细化子网的划分, 提高IP利用率.
但从麻烦的角度来说, 网络号+子网号这俩玩意 长度不固定 , 导致主机无法仅仅通过IP来确认对方是不是在我这个子网里.
那咋整呢, 聪明的前辈们搞出了一个叫 子网掩码 的东西.
子网掩码的目的很简单, 就是让计算机得知我的 网络号 + 子网号 到底多长的. 它也采用了 32bit的二进制串 , 与IP地址一一对应, 如果其所对应的那一位是 网络号 / 子网号, 则对应的子网掩码为1, 否则为0.
注意
为啥使用32bit的二进制串?
答案是为了方便计算机更快速的确认两个IP在不在同一个子网中.
只需要将两个IP分别与子网掩码做逐位与运算(相当于只保留了网络号 + 子网号, 而没有保留主机号), 再对比结果是否一致即可
我们还需要额外提一下关于上一小节说的 IP转发表 这个玩意.
这个玩意是从上向下逐条对比的, 那有没有想过如果一条都没对上怎么办?
事实上, 不会出现这种问题, 因为可以在最下侧默认设置一条表项, 其IP地址与子网掩码全部为0, 这就意味着任何IP地址与它做与运算一定全0, 一定能与这个IP对上.
这就是所谓的 默认转发路径 .
了解即可.
4.3.3 无分类编址CIDR
这个概念诞生于1993年, 当时互联网技术勃勃生机, 主机数目越来越多, 导致了一个问题, 即定长的网络分类技术的局限性愈发明显.
啥意思呢, 假如一个单位有2000台主机, 我们考虑一下它应该怎么申请IP?
- 一个A类地址下属 $ 2^{24} = 16777216 $ 个IP
- 一个B类地址下属 $ 2^{16} = 65536 $ 个IP
- 一个C类地址下属 $ 2^{8} = 256 $ 个IP
这就很尴尬, 2000不多不少, 比C类多太多, 比B类少太少对吧.
因此, 由于这种很可能造成的IP地址浪费, CIDR(无分类编址)应运而生.
CIDR重定义了地址定义方式, 将IPv4的地址简单的分为了两部分: <网络前缀> + <主机号> .
说白了, 这个网络前缀就是我们之前说的: <网络号>.
这样做能够极大的提高IP划分的灵活性, 同时也能够兼容之前的子网掩码记法.
在CIDR中, 可以将一个IP地址记作: $ 128.14.32.0/21 $ , 斜杠后面跟着的就是子网掩码1的位数, 这也被叫做 CIDR记法 .
相似的, 子网的划分也有这个问题, 因此CIDR还提出, 对于一个单位内划分的子网, 也可以采取 子网号长度不同 的方式.
这样做的好处是很明显的, 我们能够根据一个子网的具体主机数来灵活的变更其子网长度, 进而更加灵活的分配我们的IP地址.
注意
按照CIDR的分配法, 即便是最小的点对点子网, 也应当至少保留2bit的主机号空间, 这是因为我们此前说过的, 主机号全0和主机号全1的情况是不能被分配给任何子网内主机的, 它们有特殊的含义.
4.3.4 路由聚合
路由聚合是与CIDR一并使用的, 它的根本目的在于缩小路由器IP转发表的表项数目, 同时也提高检索效率. 其定义如下:
对于一个路由转发表, 如果几条路由表项的转发接口相同, 部分网络前缀也相同, 那么可以将这几条路由表项聚合成一条表项.
除此之外, 还有一个比较重要的原则叫 最长前缀匹配原则 , 它的意思跟它的名字一样, 即路由器转发的时候, 一定会选择那个与目的IP地址匹配长度最长的表项所映射的端口来转发.
用一个例子来说, 我们把路由器比作一个邮局, 现在有一条专线能够从邮局直达你们家里, 还有一种方法是邮局通过将新建先给到你们街道, 你们街道再给到你们小区保安室, 保安室再给到你.
从效率而言, 当然是从邮局直接把信件发到你们家更精确一些对吧.
最长前缀匹配就是为了最精确的将IP数据报转发到指定的主机. 如果同时有好几条前缀都能够匹配, 这通常说明有好几条路径都能转发到这个IP地址.
那还能怎么办, 肯定选最精确的那一条啊(也就是尽可能快的缩小主机地址的范围, 换言之, 就是最长前缀匹配喽)
4.3.5 网络地址转换 NAT
我们说CIDR是用于提高IP地址利用率的, 它出现的原因是因为IPv4地址太少了.
但很显然, 这种方式治标不治本, 总有一天这32位的地址会被全部填满, 那不就完蛋了?
因此, 紧接着CIDR出现的第二年, 即1994年, 网络地址转换(NAT)技术就出现了.
前置知识: 端口号
端口号其实是再上一层(也就是下一章), 传输层的一个概念, 它本质上代表着一个个在主机上运行的进程, 进程会通过一个主机上的不同端口号来收发信息. 其大小占16bit, 即可以有 $ 2^{16} \approx 65500 $ 个端口.
在传输层中, 则需要负责将对应报文的源端口号和目的端口号标明, 从而能够使得收发双方都正确地接收到传输的信息(否则你微信的消息发qq去了你不炸缸了嘛)
我们回到刚刚的问题, IP不够用了, 咋办呢?
我们会发现一个IP有这么多个端口, 所以NAT的想法就是, 把一个局域网内的多台主机分配到同一个IP地址上, 当他们需要与公网通信时, 只需要分别通过网关的那个公有IP的某一个端口向外通信即可.
这是个好方法, 它相当于将一个局域网内的所有主机当成了同一个主机, 或者也可以说是放进了同一个 子网 中. 现在的问题是:
那内部的节点怎么进行标识呢?
NAT的指定考虑到了这一点, 并通过划定了一部分 私有IP地址 来保证上述占用同一个公网IP的节点的唯一标识:
- 10.0.0.0 ~ 10.255.255.255
- 172.16.0.0 ~ 172.31.255.255
- 192.168.0.0 ~ 192.168.255.255
可见给我们分配的私网IP还是很多的哈.
最后, 考虑一个内网中的一个进程如果要与外网通信, 路由器该怎么映射这个进程到一个公网IP的一个端口上?
其实没啥复杂的, 路由器有这么一个NAT表, 当它收到向外的报文, 会主动记录下这个报文的 <内网IP + 端口> , 并主动创建一个 <外网IP + 端口> 项目与之映射. 当收到回应时, 再将回应中的目的IP和端口号映射回内网IP与端口号, 随后继续放到内网中转发即可.
当前, 几乎全部的路由器都支持NAT功能. (废话, 要不然IPv4早爆了)
4.3.6 地址解析协议 ARP
按理来说, IP地址这一大块我们倒腾的差不多了. 现在就是一些前面没有涉及到的细节. 先从这个最关键的细节开始, 怎么通过IP地址找MAC地址?
这个事情跟我们之前提过一嘴的 ARP协议 有关系. 它单独于IP协议, 设定了另一种报文格式, 专门用于干这个与数据链路层对接的活.
具体而言, ARP定义了这么些东西:
- ARP表:
- 每台主机 / 路由器都有自己的ARP表, 它会记录自己已经得知的 <IP地址, MAC地址> 的对应关系.
- 会定期更新
- ARP分组(与IP分组是同等地位)
- ARP请求分组:
- 我是谁: 标注自己的IP, 以及MAC地址
- 我要找谁: 标注自己想找的IP地址
- 将其封装进MAC帧, 目的地址设为全1(广播帧), 源地址填自己的MAC
- ARP响应分组:
- 我是你想找的IP, 我的MAC地址是这个
- 封装进MAC帧, 目的地址设为请求分组的MAC, 源地址填自己的MAC
- ARP请求分组:
当一台主机收到一个响应分组后, 就会更新自己的ARP表, 随后此后再要给对方发消息的时候就不用再问一遍了.
除此之外, 如果过程中有别的节点收到了别人的请求分组, 也会顺手将其在自己的ARP表中记下来. 这很好理解, 顺手的事对吧.
4.3.7 动态主机配置协议 DHCP
好的, 最后一个细节: IP地址怎么分配?
当然有一种方法是手动来干, 每个设备(局域网)分配一个IP, 这很好, 但不够灵活, 也不够高效.(你的设备接入网络的时候需要你手动配置IP嘛?)
因此, DHCP出现了, 它的目的就是 给刚接入网络的主机分配IP地址, 配置默认网关以及子网掩码 .
注意
DHCP实际上是一个应用层的协议, 但是由于其服务对象主要是网络层的内容, 因此我们把它拿到网络层来做解释.
通常每个需要涉及到IP分配的情景都会涉及到DHCP服务器. 因此我们将一个分配IP的过程用一个 C-S(Client - Server) 的过程模拟一下:
- Discover(DHCP 发现报文)
- 源IP为全0(在前面IP地址的含义部分有讲), 目的IP为全1(广播)
- 源MAC为自己的MAC, 目的MAC为全1(广播)
- 意思为: 我初来乍到, 先报上我的MAC地址.
- Offer(DHCP 提供报文)
- 源IP为自己的IP, 目的IP为全1(广播)
- 源MAC为自己的MAC, 目的MAC为发现报文中的源MAC
- 会在应用层(即网络最上层)的报文段中写如下信息:
- 给你提供的IP地址
- 有效期
- 子网掩码
- 默认网关
- Request(DHCP 请求报文)
- 源IP为全0, 目的IP为全1(广播)
- 源MAC为自己的MAC, 目的MAC为全1(广播)
- 会在应用层写这些东西:
- 我的MAC是…
- 我接受你刚刚给我分配的IP(xxx.xx.xx.xx)
- Acknowledge(DHCP 确认报文)
- 源IP为自己的IP, 目的IP为全1(广播)
- 源MAC为自己的MAC, 目的MAC为请求报文中的源MAC
- 应用层内写的东西跟Offer里面一样
随后, 这个新主机就有了自己的IP.
4.4 Ipv6报文
我们Ipv4倒腾了好久, 有一大部分原因就是因为IPv4的地址空间 实在太小了! . 所以搞出了CIDR, NAT等等技术, 但这些都是修修补补, 有没有一种方式从根本上解决这个地址不够用的问题?
简单, 拓宽位数不就完了.
因此, Ipv6应运而生.
我们把首部拆开来聊聊:
- 版本: 指明该数据报使用的Ip协议版本
- 优先级: 数据报的类别以及是否需要优先处理(不是很重要)
- 流标签: 从某一个主机A发送到主机B的全部数据拥有同样的流标签. 有点类似于Ipv4中的 标识
- 有效载荷长度: 扩展首部 + 数据部分的总大小
- 下一个首部: 指向有效载荷中的第一个扩展首部(随后继续向扩展首部2, 扩展首部3, …指, 类似链表)
- 跳数限制: 相当于Ipv4的TTL
- 源地址 / 目的地址: 顾名思义
一看就明白了, Ipv6的地址是 128位 , 容纳空间比Ipv4大多了!
除此之外, 我们会发现Ipv4中的分片相关的字段全没了. 对的, Ipv6将分片功能去掉了, 这意味着一个报文段只能在源主机处定好大小, 不能继续细分.
这里还需要提一下, 这个 扩展首部 是个什么东西?
扩展首部是Ipv6的一个特别的部分, 如果需要进行更进一步的功能实现, 就再有效载荷部分添加对应的扩展首部(有点类似于买游戏的时候你要整上的DLC). 这能有效提高首部的灵活性.
随后来了解一下IPv6的记法, 我们显然不能再使用点分十进制了, 太大了.
所以采用了一种比较好看的方式: 冒号16进制记法
每四个16进制一组, 总共8组, 这就是IPv6的表示形式, 感兴趣的读者还是可以继续查一下自己电脑上的Ipv6地址哈.
此外, Ipv6还涉及到一些压缩的记法, 这里就不涉及了, 不是很重要.
最后, 是Ipv4与Ipv6的适配问题.
显然, 这俩的头部差的实在是有点多, 指望这俩报文在路由器处互相转换有点太难了.
咋整? 不换了, 假如现在有个Ipv6的数据报传到了一个只支持Ipv4的路由器处, 就直接把整个Ipv6数据报作为另一个Ipv4数据报的 数据部分 , 相当于在外面套一层娃. 后面再把外面的Ipv4首部拆掉即可.
这被称为 隧道技术 .
Ipv6的内容就到这里.
4.5 路由选择协议
我们之前说网络层的功能主要是 路由和转发 , 转发我们倒腾的差不多了, 就是路由器将分组转发到其另一个接口的过程.
现在的问题是: 路由 怎么实现?
首先, 路由的含义是, 在已知当前节点和目的IP节点后, 如何选择一个最优的路径来将该分组转发过去?
其实说的简单一些, 就是该 走哪个口 ?
路由选择协议大体分以下几个部分:
- 内部网关协议:
- 一个AS内使用
- RIP: 距离向量
- OSPF: 链路状态
- 外部网关协议:
- AS之间使用
- BGP
概念: 多播地址
自治系统(AS)是互联网中由一个或多个实体管理,并遵循统一路由策略的IP网络和路由器集合.
读者大概只看这一行不会很明白AS到底是个啥, 别急, 我们往下慢慢聊.
4.5.1 RIP协议与距离向量算法
RIP协议适用于相对较小的AS, 基于 距离向量 算法.
它的核心思想是网络中的每一个路由器都维护一个从它自己到别的网络的最佳距离记录, 长这样:
$$
\begin{array}{c|c|c}
目的网络 & 距离 & 下一跳路由器 \\
\hline
Net2 & 1 & 直接交付 \\
\hline
Net1 & 2 & R1 \\
\hline
Net4 & 2 & R3
\end{array}
$$
有了这个图, 我们大致就能明白RIP是在干什么, 以及其要记录的信息是什么意思了.
但, 这些信息怎么来的呢?
RIP制定的规则是: 每个路由器只和与自己相邻的路由器交换信息, 每次将自己当前的路由表告知邻居路由器.
而每次路由器收到相邻路由器的一条信息, 都要对自己的路由表进行一个更新:
这说起来有点抽象, 啥意思呢.
比如说我是路由器1, 现在已知一条到子网3的路径距离为10.
现在跟我相邻的路由器2把它的路由表告诉我了, 而恰巧它表内有一条表项, 说它到达子网3的距离为5.
那我就应该将这个距离为10的玩意更新掉, 然后填上我到路由器2+路由器2到子网3的距离 = 6, 因为显然它更短. 同时将下一跳改为路由器2
其实本质上就是一个最短路算法, 如果读者有了解过数据结构中 图 部分的内容, 会发现这就是贝尔曼-福特(Bellman-Ford)算法.
我们系统的总结一下RIP协议中路由器收到相邻路由器的报文消息后该干啥:
- 修改相邻路由器X发来RIP报文中的所有表项:
- 把 下一跳路由器 改为X
- 把距离+1
- 对修改后的RIP报文进行如下判断:
- 如果本路由器表内没有对应条目到达的子网, 则将该条目填入本路由器表中
- 如果本路由器表内有对应条目到达的子网
- 若下一跳为X, 则用收到的表项直接更新当前表项(说明这个邻居路由的路径发生更新了, 那我这边也得更新)
- 如果下一跳不是X, 则比较原表项和新表项距离的大小, 填入小的那个(比较一下新路径跟源路径那个近, 走近的那个)
- 如果超过180秒没有收到路由器的信息, 则将对应的距离更新为16
注意
RIP协议设计的最长跳数是15, 如果距离为16, 则认为该位置不可达
这种传输方式会带来一种很严重的问题, 即 坏消息传得慢 的问题.
读者可以自行假设一下, 上面的路由表中, 有一个路由器突然断掉了, 会发生什么?
这里我就不写全过程了, 笔上模拟一下能够得知, 这个坏消息不会立即被别人得知, 而是反复+1循环, 直到两方都循环至16后才能发现问题.
最后, 明确一个事情, RIP也是 应用层 的一个协议, 在传输层会使用UDP协议传输, 它之所以放到了网络层中讲解是因为它与网络层的功能息息相关.
4.5.2 OSPF协议与链路状态算法
OSPF相比于RIP能够适用于更大的网络, 同时其本质上采取的算法是一个我们很熟悉的玩意 迪杰斯特拉最短路径算法 .
OSPF的工作过程如下:
- 用HELLO问候分组来发现它的邻居节点以及网络地址.
- 评估自己与邻居节点的链路成本度量
- 向相邻节点发送自己的全部链路状态的摘要信息.
- 相邻节点收到信息后, 通过迪杰斯特拉算法来更新自己的链路拓扑图以及最短路径转发表.
- 返回一个LSack确认分组
- 当链路发生变化时, 重复该过程.
还有两个点:
- OSPF每隔30分钟必须强制更新一次数据库中的链路状态.
- 相比于RIP, 更适用于规模较大的互连网
4.5.3 BGP: 域间路由协议
这一部分博主就不按照王道的讲解来了, 当前王道的免费网课(2025)并未更新关于路由选择协议的内容, 而此前的版本讲的又着实过于简略, 因此还是以书为准.
我们此前说的那俩都是运用在同一个AS内部的协议, 现在问题来了, 两个AS之间的通信怎么解决?
这个问题就是BGP尝试解决的玩意.
在互联网的当前设定中, 不同的AS会有一些 话事人(也叫网关路由器) , 它们负责着将本AS中的流量向别的AS之间转发的工作.
作为话事人, 它们必须要担当的职责主要有两方面:
- 告知本AS中的服务器, 我能到哪些别的AS
- 告知外部AS中的服务器, 哪些服务器能从我这里借路到达
这两方面的任务会通过 iBGP 与 eBGP 来进行解决, 我们一个个谈.
eBGP : 向其它AS做出能够到达目的地的宣称与路径.
eBGP使用的通信信息通常被称为 路径通告 . 通常包含两部分: (通过AS的路径, 目的地).
比如, 上图中, 假设以3d为目的地, 3a会向2c做出宣告: (AS3, 3d), 意义为: 能通过我这个AS3的话事人到达3d.
而经过iBGP(下面会讲)的通告后, 2a同样会做出如下宣告: (AS2, AS3, X), 意义为: 能通过我这个AS2的话事人, 我们AS2再把这个报文转给AS3, 进而到达3d.
iBGP : 向本AS内部的所有路由器告知我能到达的全部地点.
当本AS的话事人得到外部网关的宣称时, 它会将该宣称在本AS内部广而告之.
这样, 本AS内全部路由就都知道了我能通过这个网关把消息传出去.
现在的问题就是怎么把消息传给这个网关?
那我们知道啊, 前面的OSPF和RIP干的就是这个事情.
还有最后一个问题: 如果本AS内有多个网关都能到目的地, 选哪个?
本质上也就是要知道AS内部是通过什么策略来决定转发的网关的, 这玩意叫 Hot-Potato-Routing(热土豆路由) .
它的思路就是我要选择离我最近的网关, 赶紧把这个报文扔出我的AS. 至于AS之间的路径开销, 我不管.
举个例子, 上图中2d要给X传报文, 它会选择2a作为网关而不是2c, 因为它离2a更近.
最后, 明确BGP运行在应用层, 它通过传输层TCP协议来对接, 使用端口179.
4.6 SDN控制平面
这一部分也是王道没有的, 但是在计算机网络中占据的低位挺重要, 还是拿出来说一说.
我们在4.5中倒腾了半天, 其实本质上都是在寻求一种方案, 怎么让路由器找到正确的转发路径.
有没有一种方法, 让这个过程变得更简单, 更高效?
有的兄弟, 有的. SDN控制平面来了.
SDN的思路非常非常简单, 我把上面做出的全部运算过程放在集中式服务器中先算完, 随后集中式服务器定期向下属路由器分发它们的转发表.
相当于路由器不用动脑子, 会照着集中式SDN服务器给的转发表干活就行.
SDN控制平面通常通过 OpenFlow协议 来进行数据沟通, 我们不需要对这个及其复杂的协议以及其过程有很深的了解, 只需要知道这两点:
- 下层路由器负责报告链路状态, 传给SDN服务器
- SDN服务器计算出每个路由器的转发表, 发回给下层路由器即可.
相当于是将这个过程中心化了.
网络层最核心的内容就介绍完了, 这一章写的其实挺艰难的, 因为王道的课在这一章着实称不上详细, 因此很多内容需要我们自己来扩展.
网络层还有些有趣的协议, 比如 SNMP(简单网络管理) 和 ICMP(互联网控制消息协议) , 它们至今在网络中也起到很重要的作用, 但是这里就不再过度展开了, 读者可以自行继续了解.
这篇博文就到这里~