呼,写了这么久终于重新开始啦!
自己落下了太多东西了.....是时候应该重新拾掇起来了.
关于后面的代码项目,我的想法是vilas.js仍然使用js来进行编写,但是后续其他的项目会开始尝试使用ts来进行书写了. 就算是前端也需要点规范吧.....
这篇文章要和大家道个歉,首先是拖更了很久,其次是对于这个内容可能也稍微粗糙一些,欢迎随时在评论区或者私信提问,也支持通过各种渠道联系我,你的帮助是我最大的动力.
在过去的两个月里的生活收到了比较大的冲击,不过目前已经慢慢稳定下来了, 我不会在团体上倾注太多感情了, 但从今往后我也不会再违抗我自己的想法和可以压抑自己的情感, 纯粹和赤诚的喜欢,不在乎过程多艰难,也不在乎有没有结果,我会尽力去奔向我想要的一切,无论未来也好,技术也好,你也好.
end
网络层实现的是将分组从主机通过多个网络传递到目标中,在这个网络层中,我们传递的数据被称之为"分组".通过各种IP,路由选择等等操作,将其送到目标地点.
其实最显著的特点就是传输范围,在传输比特的时候,我们在链路之间传递.传输帧的时候,我们在一个网络内传递,网络层则进一步扩大,在多个网络之间传递数据,真正意义上地在"互联网"上传递数据.
如图所示,网络之间通过路由器这一结构来实现交互.在这个结构中,我们需要解决的就是有关于网络层提供怎样的服务,如何在网络层找到主机等等工作.
别急,你先别急,在后面我会慢慢解释
网络层需要传递的是分组,这一数据结构,所谓分组就是我们要把运输层传过来的报文段,给拆分成多个"分组",因此我们要考虑的是这一系列的数据,是如何传递的.比如如何保证顺序,如何保证不丢包.
还有,我们需要知道在网络这个拓扑图中,我们需要找到什么路径,来传递这个分组(回忆一下数据结构的内容中,我们学习过很多的图最短路径算法,其实在计算机网络中我们没有一个统一的代价标准,有些网络拓扑路径可能看似很长,但是从安全性角度来说,反而是更合适的道路)
因此我们可以看出我们需要解决两个问题:分组以何种方式进行转发,以及如何进行路由选择(路径选择)
在源主机和目的主机之间可能存在很多条路径,并且通过路由器转发这些分组,在每个分组进行传递的时候,分组的头部都会带上地址.而路由器中的路由表则会进行一一对比, 寻找出这个分组下一步该往什么地方移动.
比如这个路由器有三个端口,其中一个端口收到分组以后,会按照表中指定的特定的方向进行传递分组.或者做其他处理.
而在网络中选择那一条路进行路由传递,最终到达目的网络中的主机上,就是路由选择要去做的事情.
当然,这部分在这里肯定是解释不清楚的,我们放在后面进行解释.
别急是一种态度.....
我们必须考虑分组是如何进行转发的,在网络层中,我们根据传递方法的不同区分为两种方式,面向连接的虚电路服务,面向无链接的数据报文服务.
面向连接这个词的意思就是,我们通过构建一个逻辑上的电路,专门用来输送一系列数据,如图所示
在这样一个网络层中,我们建立了一个逻辑意义上的电路,这一点和我们在第一章中所说的电话线路异曲同工,不过这里是在逻辑上的电路,所以称之为虚电路.
在向网络申请完这个电路结构以后,在一段时间以内,这个虚拟链路只负责传递特定的数据,换句话说就是专用线路,直到线路资源被释放.
在构建完成线路以后,我们将数据划分为多个分组,并且按照顺序在这个电路中传递,其中用传递分组在建立电路的时候,头部需要标记目标地址. 但是在线路构建完成以后,分组只需要标记虚拟电路的编号就可以传送数据了,这也体现了一个专用的特点.
在线路使用结束以后,释放这个线路资源.
虚电路服务的特点就是,分组在传递时候,误码,丢失,重复和失序问题是可以由网络本身进行保证的,或者说提供的是一个比较可靠的服务.但是缺点也很明显,占用大量资源的同时,也需要频繁释放一些资源.
其实刚才说分组传递的时候你就应该想到,为啥有的分组只用存虚电路编号,但是我每次抓包或者听别人说都是需要ip地址.
那是因为,
这个方法早就被放弃了,现在因特网的开发者们更倾向于另一种模式,也就是面向无连接的数据服务
其实现在更倾向于使用这种方法来进行处理,核心思想就是"将可靠通信交给用户主机来保证",而不是交给网络来决定.这种传递分组的方式极大地释放了网络本身的压力,但是带来的问题就是我们俗称的丢包等等.
两台计算机在进行分组数据交互的时候,不需要建立连接,因此每个分组都是自己负责独立传输的,在首部都需要带上目标的源地址.每个分组都可以走不同的路径
而网络的具体处理,由端/边缘层进行实现.本身提供的服务类型其实算不上可靠,但是胜在方便,因此会成为一个很重要的方面.
而这种服务,也就是我们下面会提到的所有服务,算法和网络的基础
IP协议规定了在多个网络的主机之间相互传递消息的规范,是TCP/IP协议体系中网络层的核心协议(注意并非唯一协议,是核心).特别说明,在本篇博客中,只介绍IPv4这种地址以及衍生(事实上IPv4地址已经在13年左右停止继续发送了).
IP协议是该体系中的网络层核心协议, 与之配套使用的还有地址解析协议(ARP),逆地址解析协议(RARP),网际控制报文协议(ICMP),网际组管理协议(IGMP),其大致关系差不多是这个样子的
这四个协议辅助IP协议,完成了网络层需要干的大多数事情,(另外注意一点,RARP协议理论上来说目前已经停用了)
另外在介绍IP以及相关问题的时候,还是要先说明一下网络的结构.
对于网际层来说,面对的网络指的是很多"异构网络"组成的一张大网了,异构网络指的是参与构成互联网的不同网络(局域网),他们通过路由器完成彼此的链接,每个异步网络内部都有自己的需求,自己的拓扑结构以及性能协议.而IP协议实现的就是这些结构进行封装,对于用户来说,无需考虑不同异构网络内部的信息是否不同,就好像在一个网络上通信一样便利.
异构网络的体系结构如图所示吧.
有了这样一个概念以后,接下来将会介绍的是"如何寻址"
(提前说明,在这篇博客里不会提到关于IPv6的有关事宜,但是IPv4已经在2011年停止发送了,虽然在此之前人们想到了很多办法去解决地址不足这个问题, 但是终究还是抵挡不住太多的需求)
(唉,有的时候就像喜欢一个人一样,真的要在梦想和放弃之间做个抉择,希望我早日能有自己的决定吧)
IPv4地址是在IP网络上,给每个主机/路由器的每个接口单独分配的唯一地址(全球范围内唯一),也就是说精确定位公网IP以后,理论上就能找到哪个机器.IP地址是一个32位比特的表示符号,将其转化为10进制,并且用逗号每八个比特进行一次区分,就能得到一个我们最常见到的形式
11,22,33,44: 这也就是我们俗称的IP地址,书写成这种形式是为了方便用户使用和识别.
IP地址中,无论是何种编址方式,都要指出网络号,以及设备号
历经历史的变化,目前的编制方式一共有三种
1. 分类编址
2. 子网划分
3. 无分类编址
其中前两种的编址方式已经被完全淘汰了,不过仍然是一种历史变化的过程,所以在这里仍然要写出来.
分类编址其实要我来说,其实就是人类一开始最直观的体现,我们通过规定,提前认定某些位置是网络号,其余位置是设备号. 对于分类编址来说,根据开头连续的1的数目,我们将其划分为五个固定的地址匹配类型:
其中只有ABC三类地址可以分配给网络中的主机使用(这不废话么,只有他们存在主机号), 这样一来,每个编号负责什么工作其实已经一目了然了.
但是这里要注意一点情况,这也是后面其他的编制方式同样需要注意的,我们以C类地址为例
C类地址中,主机号一共由8位,这就代表我们一共可以找出256个设备号,但实际上能用来分配的仅仅只有256-2,这是因为设备号比特位全为0的时候,这个地址称之为网络地址,是用来代表网络本身的而不是某个设备,需要保留.还有设备号比特位全部为1的时候,这个地址称之为广播地址,干什么的就不用我多说了对吧?这两个地址要预留出来,不能用来分配给其他的网络,这一点无论是在其他编址方式,还是划分中,都是要注意这一点的
所以说这里可以总结出一个公式,对于某个类型的网络,其网络号为n位,设备号为32-n位,并且网络号前面的保留位置为x位,那么这个给行的网络可以分配的主机一共
分类编址其实是很符合人类直觉的,但是随着网络需求量的不断扩大,分类编址的问题也很明显了,首先申请的一个网络号设备有限,如果是不够还好说,申请更高等级的网络就好了.但是如果一个小组织申请了一个C类地址,但是无法用到所有的设备号,这就造成了一定程度的浪费.
因此后面的两个方法都在逐步解决这个问题,那么如何解决呢?
核心工具就是"子网掩码"/"地址掩码"
在上层的基础上,为例不免IP地址的浪费,通常是由ISP将一个IP地址的设备号分给自己下属的多个组织,也就是为每个"部门"划分出一个子网.可以让分配更加灵活.
例如,我们现在有一个C类地址,里面有254个设备号可以分配,我们可以让64个给开发部,剩下的都给设计部这样子,这就是子网划分.
而在IP地址中,子网划分的体现就是在原本的网络号的基础上,占用几位原本的设备号,形成"子网号",将一个IP地址完整地划分为网络号,子网号,主机号三层结构:如图所示
而为了注明,主机号哪几位被占用了,我们在IP地址的同时附带一个"子网掩码"的结构,也是一个32位比特的特征码,对应到真实的IP地址中,子网掩码为1的部分,就是划分为网络的区域,子网区域划分为0的部分,就是设备号的区域.
在每个网络都有自己的唯一子网掩码,而且各个设备之间都是统一的,来表明这个网络的划分情况.在后面的路由跳转中提到了这样一个计算:
使用本网络的子网掩码和设备IP地址进行按位与运算,即可得到这个设备所在的网络的地址,也可以算出其他设备和本设备是不是处在同一个网络内(因为如果是同一个网络,使用同一个子网掩码计算的结果应该是一样的)
在这里需要说明一个大家可能会犯的误区: 子网编址确实是从分类编址发展起来的,但是并不完全遵从ABC类地址!本质上这是两种分类方法.
我知道为什么会有这个误区,因为子网掩码这个分类方式本身就是怪怪的,鱼和熊掌都想要的感觉,所以庆幸这个东西已经被淘汰了吧...
接下来将会介绍一种目前在用的无分类编址方法,这种方法摒弃了这种奇怪的三层结构,转而使用更加灵活的方式,这也就是发挥子网掩码/地址掩码真正效果的时刻了
划分子网的方式对于缓解压力有用,但不是完全有用,IETF最后的挣扎便是误分类编址
无分类路由选择,又被称作"CIDR"码,这种编址方式取消了之前的ABC以及子网划分的概念,冲洗娘划分子网的三级结构(网络,子网,设备)转化为了两级结构,但是这个两级结构的称呼发生了改变
不定长的网络前缀(对应以前的网络码),以及设备号.
这次整个网络的部分都是不定长度的,因此我们需要一个类似子网掩码的结构来划分,究竟什么地方是网络,什么地方是设备,这种同样不定长的掩码,我们称之为"地址掩码"(因为无分类编址的方式, 取消了子网的概念,但是习惯上称之为"子网掩码",也是没有什么问题的).
对于这种编址结构,我们的地址掩码可以使用全新的标识,被称之为斜线记法/CIDR记法,在IP地址的后面直接标注前多少位为网络前缀.
使用CIDR的好处就是,可以更加有效地分配IPv4的地址空间,可以根据客户的需要划分模块
另一个好处就是方便路由聚合,比如在路由器的路由表中(这个部分也会在这篇博客中提到),一个路由器代表一个表,这个表注明了不同的目的网络该走什么样的端口,所以对于一些划分的子网来说,经常会出现这种情况
其实某种意义上来说,同一个网络下的子网,像是这样进行分别记录,极大地消耗路由表中的内存了,因此对于一些相同前缀上的路由表可以进行路由聚合,比如这样
只要是符合这个前缀的,都直接送到R1路由器上,减少了R2这个路由器的内存负担(关于具体怎么样匹配,后面也会说到)
举出一个现实生活中的例子: 比如捡到一个身份证,我们可以根据背面的信息,将其直接交给派出所,而不是自己根据地址送上门.这就是路由聚合的作用,派出所在这里就起到了一个聚合效果
从上面的例子可以看出网络前缀越长,地址块就越小,路由就越发的具体,在CIDR这种编码方式下,诞生了一种叫做最长前缀的匹配方式(不过我愿称之为匹配---最长),路由器通过这个来生成具体的跳转动作和衍生算法..
嘛,不过这些是后话了.
其实IPv4的地址规划在上面的编址方式已经说的很清楚了,主要分为定长的子网掩码和不定长的子网掩码两种类型,前者相对来说不够灵活后者相对来说更灵活一些.
但是这个东西在这里要强调一点就是:
在划分网络地址子块的时候,尤其要注意给每个子网块分配一个网络地址,一个广播地址作为设备好,如图所示
剩下的倒也没什么,如果需要其他补充请在评论区联系我
在前面我们说到,IP地址和MAC地址是存在一些联系的,IP地址同样可与指向具体的某个接口位置,因此在这里我们需要对两个东西究竟有何联系进行一些区分
其实通俗点来说,IP和MAC是在不同的层发挥作用的地址,IP是网络层用来寻找某个接口的地址,因此会封装在网络层的PDU首部
而MAC地址是在数据链路层发挥作用的,因此封装在帧的PDU首部
如图所示
因为所在位置的不同,发挥功效的时间地点也完全不一样
在传递数据的过程中,IP的源地址和目标地址是不会变化的.但是在这个过程中每到达一个新的网络内部,MAC的源地址和目标地址就会发生一些变化.
地址变化的示意图如下
其实我一开始学的时候一直有这个问题,既然IP地址和MAC地址都可以精确地标识每一个位置的区别,那么为什么不使用其中一种呢?
首先就是IP地址和MAC地址的位置不一样,发挥的具体作用原理也不同,这是第一点.
其次,IP地址作为更上一层的封装,就可以减少路由器中的路由记录,而不是记录各个接口MAC地址,因此如果全部使用MAC进行定位,代价是很大的,因此MAC只能在一个网络内部单独使用.
再然后,因为IP地址是可以重新分配的,所以IP地址会发生变化,但是MAC地址是设备独有的,一般不会轻易发生变化.
因此,二者的关系已经很明显了,那么如何进行二者的转化应用?就是ARP(地址解析协议)的作用了
地址解析协议(ARP)的功能是:通过已知的IP地址找到对应的MAC地址
逆地址解析协议(RARP)的功能则是:通过已知的MAC地址找到IP地址
由于这个世界上存在着大量的异构网络,不同网络内部的MAC协议都是不一样的,因为为了实现自由通信,就必须实现复杂的MAC转化机制
数据报文的传递包括两个部分,首先是主机如何传递数据报文.,另一个是路由器如何传递数据报文.
(补充一个网关的概念:网关通常为路由器的地址,是一个网络内该往哪里跳)
在IP数据报进行转发的时候,要注意的一点就是注意使用地址掩码,在后续的一些内容中,我们会直接给出网络号而不是具体的设备号,是因为这里是需要进行一定的计算的,关于如何计算,我们将在下面的两个小部分来进行更新.
主机转发数据报文一共有两种情况,第一种情况被我们称之为直接交付,指的是同一个网络中的主机进行交换数据. 而另一种情况称之为间接交付, 指的是源主机和目的主机不在一个位置上,在这种情况下就需要通过路由器进行交互.
主机转发报文的情况下,需要实现的一个功能就是"判断目标地址和源主机是否在同一个网络内"
这一点的方式,使用源主机中的子网掩码,来计算目标地址和自己是不是处在同一个网络号中, 如果不在同一个网络中,就要发送到默认的网关中(网关:补充概念,这里指的就是路由器,作为一个默认输出的渠道来进行处理)
举个例子:
比如这个主机A,想要向主机D,也就是地址192.168.0.129发送一个数据\
首先A先根据子网掩码,和子网掩码进行按位与的运算,得到源地址所在的网络为192.168.0.0
然后根据这个A的所在网络的子网掩码,计算目标地址的"所在网络192.168.0.128(这是二进制的计算原则,这里就不展开计算了, 不过这里要说明,这个东西是计算不出D的真实地址的,只是想在同一个子网掩码下计算看看结果是不是一致的,如果一致则一定在同一个网络内部)
因此可以看到,二者得到的"网络地址"是完全不一致的,因此可以断定二者不在同一个网络中.
主机需要顾及的问题就是目标在什么地方,而路由器在传递报文的时候需要处理的问题就是,如何查询匹配的路由条目(在自己的路由表中),其实这个计算仍然是参考了我们之前提到过的子网掩码的计算问题:
如图所示,在这样一个间接交付的路由过程中,A向D发送数据,那么数据报文中的目的地址是如何匹配到路由表中的?
计算逻辑是这样的,利用目的地址,来计算每一个条目中的地址掩码,然后看计算出来的"网络地址"和条目中真实的网络地址匹配,如果匹配成功,就根据该条目中的路由指示的端口来进行跳转.这就是路由器发挥的作用.
(在这里详细解释了路由器的原理,在后面关于路由器的其他拓展,就不会再描述具体了,只会说"和对应的网络地址完成匹配")
如果查询到了匹配的路由条目,就按照该路由条目的指示来进行转发
如果查询不到匹配的路由条目,那么就丢弃该IP数据报文,并且向发送该数据报的源主机发送差错报告.
IP数据报文需要头部来保存一些信息,这个信息不需要全部记忆,在这里只保存一些重要的内容进行详细的解释,由于一些特殊原因.IP数据报文头部的长度为20-60字节不等(20字节的固定长度以及最大40字节的可变长度)
多吧,我也知道很多,我也不想写.......
版本:版本占位四个比特,用来表明协议的版本
首部长度:展位四个比特,单位为四个字节,用来标识这个IP数据报文的头部的长度,例如四个比特的最大数值为1111,也就是15*4=60个字节
区分服务:用来获得更好的服务,但是这几个位置一直没用到过
总长度:单位也为4个字节,长度为16个比特,和计算首部长度的方法类似,代表的是整个IP数据报文的长度,(总长度-首部长度)*4即为总共的数目.
标识,标志,片偏移.这三个字段适用于数据的分片,在进行向下封装的时候,肥肠要注意的一点就是,帧的数据载荷是有限的,因此过长的IP数据报可能会导致无法正常封装为下一层的PDU,
因此需要用某种手段将数据给分片处理,并且还要保证分片以后还能正常保证次序,也就是组装起来.
标识:一共16个比特,用来标识数据的分片来自同一个IP数据报文.(也就是同一个IP数据报文生成的分片,具有一样的标识.类似ID的作用)
标志:标志主要是一些功能位置,如图所示
片偏移:用来表示分片以后的IP数据报,其数据部分是从原本IP数据报的什么地方开始的,单位为8个字节,
以图中这种情况简单计算一下,第二个分片开头是从1400开始的,因此这个东西在片偏移字段的内容就是1400/8=175对应的二进制数字
生存时间:这个是很重要的东西,用来保证数据报文的传递次数,传递长度等等,在之前是一个计数器,但在现在是一个名为TTL的生存时间的机制,每次跳转到新的路由以后, TTL--,直到最后变成0,这个数据报文就会被抛弃了,然后返回一个超时报文.
协议:用来指明上一层带来的协议,也就是IP数据报中数据载荷是何种数据协议包装的单元(害,运输层来的,不是TCP就是UDP了)
首部检验和:用来检测的
源地址IP和目标地址IP这就不说了
静态路由协议配置指的是在进行路由器中路由表配置的时候,由于一些特殊情况,程序员或者网络管理员人员不得不手动配置一些相关的路由辅助跳转(类似我们在程序中手动添加的条件判断语句,可以说有一点相似之处).这种情况一般只在小型网络中能达到比较好的效果,因为无法随着网络的拓扑结构而更更新,通常作为辅助使用
如图所示,路由大致可以分成两种主要形式
直连路由:直连路由指的是,对于一个路由器来说,和自己直接相连的网络的路由,则被称之为直连路由.这种路由在路由表内的记录形式是直接的接口位置,也就是能够直接得到该往什么接口传递数据,这种东西是路由器自行得出的路由,会随着拓扑结构的改变而改变
非直连路由:非直连路由指的是,对于一个路由器来说,和字节无法直接相连接的网络,被称为非直连路由,这种路由一般是被程序员自己设置的,因此这就是静态路由
非直连路由的特点就是在路由表中,条目中无法记录下一跳的接口,而是像这样,保存一个人为指定的IP地址
看吧,比较明显,但是这里带来的一个问题就是这种东西该怎么跳转,因为没有指明路由器下一步操作应该怎么做,这里很简单,通过路由匹配得到下一跳的地址应该为一个静态的地址也就是10.0.0.2,那么接下来就重新把这个新得到的地址重新投入路由器进行下一次匹配即可.(其实理论上来说这里会发生死循环的问题,不过网络本身肯定是有机制去避免这些操作的,习惯就好)
程序员设计静态路由肯定是为了处理一些特殊情况,所以说这里会说明两种用的比较主要的路由,以及为什么可以使用这种路由的匹配方式
在这之前,我们要解释什么是最长前缀匹配,有时候计算出的网络地址可能和多个地址适配,因此我们需要选择其中一个路由条目进行匹配.
最长前缀匹配,我个人认为这个名字是很有歧义的,可能是因为翻译问题,如果是我自己的理解,我愿意将其称之为"匹配-最长原则"
因为这个原则是需要两个步骤先后发挥作用, 首先是匹配,匹配指的是根据目的的地址和条目中的子网掩码计算出来的网络地址,以及该条目中给出的地址,需要和条目中的各个网络地址都进行比较(下面的图中的条目直接给出网络地址而免去了计算过程),筛选出所有匹配的网络地址
其次才是最长,在这些符合的网络地址中,选择有效位置(网络前缀)最长的一个.
有点抽象,这里我们可以举个例子.
我们在这里有两个路由条目
网络地址:198.87.1.0 /17
网络地址:198.87.0.0 /16
数据包地址为198.87.1.100
(1)关于"匹配":
在第一个条目中,通过17位置网络前缀,计算出的数据包的网络地址为198.87.1.0,和该条目中的地址是一致的
在第二个条目中,通过16位置的网络前缀,计算出的数据包的地址为198.87.0.0, 和这个条目中的地址也是匹配的
(2)关于最长
这两个匹配的路由,一个的长度为17,一个的长度为16,因此前者更长,我们选择前者
通过这两个原则,就可以实现一个比较科学的选取方式.下面会以这个未接触,讲解什么是默认路由和特定主机路由,以及为什么优先级最高
(注意这个优先级,我个人觉得指的是先进行匹配以后的路由的优先级)
默认路由匹配的内容其实很简单,就是全0
0.0.0.0/0 ,对,没错,就连子网掩码都是0
这个的特点其实就是,在匹配的过程中和所有的目标地址都能完成匹配,但是在最长的判断阶段,优先级是最低的.如果你写过promise相关的异步操作,你就能发现这个和catch是一模一样的功效.
(换句话说,ifelse里面的else字段)用来作为一个兜底的情况
出于某种安全考虑,为了让运维人员更方便地控制网络和测试网络,需要具体指明特定的主机
这种东西就类似if,和默认路由匹配不一样,优先级最高,路由展示也最具体
IP地址/32,子网掩码是满的,前面其实落下了一句话,子网掩码越长,地址越精确,那么32位的子网掩码就是能得到完整的地址.
嘛,其实最后的两个匹配方式也没什么说的,这里就简单说了,主要理解一下最长前缀原则,也就理解这两种匹配是在干什么了.
对于小型的静态网络来说,人工指定的方法简单开销小,维护也不是什么大事,但是无法适应网络本身的变化,因此对于一些动态的大型网络来说,需要某些协议来动态地维护路由的表,这也就是我们接下来要说的动态路由选择.
互联网所使用的协议大概有三个特征,自适应,分布式,分层
其中分层指的是将整个因特网划分为多个小的自治系统(Auto System),一个ISP就可以划分出一个AS分组.如图所示
如图所示,将一个因特网划分为多个AS,每个AS内部都是独立的,可以私用自己的内部协议
而AS之间也需要别的协议进行交互
对于AS内部的协议,我们称之为内部网关协议,在这篇博客中,我们主要提及路由信息协议(RIP),开放最短路径协议(OSPF).而对于AS之间进行交互的协议,我们称之为外部网关协议,这里仅提及一种边界网关协议(BGP)
这里是常见的网关协议
接下来会根据三个网关协议,分别解释这三个协议的算法,以及如何发挥作用
路由信息协议是内部网关协议中使用最广泛的一种,对于RIP来说
RIP要求每一个路由器都要维护从他自己到自治系统内每一个网络的举例,这个举例被称之为距离向量(DV)
为了更好的维护,RIP使用跳数(每次到达经过路由器称之为一跳,其实也很合理对吧)来衡量距离向量,默认情况下,当跳数超过16的时候,就认为太远了,因此RIP只能适用于小型互联网
以图片为例:
对于RIP来说,好的路由就是总路径最短的路由.但是如果到达同一个目的网络,有多个路径长度相同的路径,则可以进行等价负载均衡,意为将通信的数据均匀的分布在这些线路上进行传送,而不是逮着一只羊薅羊毛.
RIP只和邻近的路由器交换信息,交换自己的路由表,来更新和维护自己的拓扑状态,并且这种操作是周期性交换.
RIP的路由表更新逻辑和一些最短路径算法很接近
1.初始化:在初始化的时候,路由表中只存储自己相关的直连网络,也就是距离1
2.和其他路由器进行交换路由表,并且更新自身的信息:
这个是重点,其实也有点不是太好理解,假设我们现在有两个表更新路由信息,A向D发送自己的路由表,我们会做如下的操作
我们把C的路由表交给D,这时候交给D的表我们需要做一点改造:下一跳全部标注为C,然后距离+1
这个时候根据这个改造的表进行更新,更新的原则如下:
1. 如果是从相同的下一跳,到相同的网络,则更新D表中对应条目的距离
2. 如果通过别的路由器,到达同一个目的网络的距离更短,则更新D中的距离和下一跳路由器
3. 如果是D中原本无法到达的网络条目,则在D中增加这一条目
4.,如果是通过别的路由器可以到达同一个目的网络,但是距离和目前D中存储的距离一样,则增加这一路由条目作为负载均衡的可用线路
可能解释起来很抽象,这里按照这个实际的例子来作解释 :
从C表中的路由条目开始遍历:首先是
在D看来,从C到达N2需要2的距离,但是这里会将其更新为距离5,因为D认为这是拓扑结构变化的"最新消息"
然后是第二个路由条目 N3 9 C,可以看到D中原本无法到达N3,所以加上这一路由台哦木
N6 5 c,因为到达N6比D中原本通过F的到达路径更短,所以修改这一路透条目
N8 4 C,作为负载均衡处理
N9 6 C,忽略,因为这是更长的路径
所以改造以后的结构就是
(以上就是RIP计算路由的方法,这个东西很重要,我猜考试肯定要计算的)
其次RIP还具有一些其他时间参数,这里就不加解释了
RIP算法存在一个比较明显的缺点,称之为"坏消息传播慢"
如图所示,由于一些错误路由,可能会导致一些错误(比如死循环)
这个问题的处理方法之一就是16的最大跳数,当然这只是其中的一种办法,其他办法在这里就不加以解释了,如果有需要请联系我,我可以将其解决.
其实对于OSPF来说,可以理解为这是一种开源算法,协议本身并不是由单一商家控制的,oSPF是根据链路状态来计算最短路径的代价(也就是链路的长度或者传输速度什么的,不同的协议实现者会规定线路的不同cost),根据这个cost来进行最短路径的寻找.
这个思路是不是有点眼熟?迪杰斯特拉算法?
某种意义上没错,因为这个东西就是迪杰斯特拉本人搞出来的
(谢谢熬)
在算法上保证了不会产生RIP一样的路由环路,因为算法本身就是diji,我们在这个协议中要做的就是如何去维护这样一个图结构
链路状态:链路状态指的是路由器和哪些路由器相邻,以及链路相关的代价,
在OSFT协议中,路由器之间首先是要建立一个简单的链接,保证彼此的存在(因为要维护图结构,就要保证每个节点都是活着的).在这里我们称之为"Hello"交互问候分组,路由器之间通过这种东西来维护交互关系.
在默认情况下,路由器之间每隔10s发送一次交互问候分组, 如果超过四十秒没响应,就认为这个路由器死掉了,需要重新更新拓扑状态.
那么这里问题就来到了,如何维护拓扑状态?:
介绍一下路由状态通告LSA: LSA内部存储了该路由器附近的链路状态信息. 这个东西封装在链路状态更新分组LSU中, 并且使用如图所示的洪泛法发送给其他的路由器
洪泛法的意思是:一个路由器的某个端口接收到了一个数据,那么会在其他端口转发这个数据.洪泛法确实本身会带来一定的问题,因此这个方法害诞生了不少的改进版本
嘛,不过都是后话了
根据lSU在这个拓扑结构中的不断传递,最终我们会保证每一个节点都能完全知晓这个网络中各个节点的信息,比如自己到每个路由要经过谁,怎么样的代价,简而言之就是,在逻辑上构建了一个完整的拓扑网络,然后根据这个拓扑网络来实现最短路径求解的过程.
而这个逻辑上的拓扑结构,我们在实际上是使用一种数据库来存储的,这个工作被称之为"链路状态数据库"(LSDB),用来存储各个路由器的LSA,然后根据这个LSDB,得到一个比较完整的拓扑路线
另外OSTF有五种分组,这里就不展开意一一叙述了
大致的工作流程就是:
1. 首先,路由器之间每隔十秒发送一次问候分组建立邻居关系
2. 建立邻居关系以后,发送数据库描述分组,告诉邻近的路由器自己的状态
3. 接收到别人发来的数据库描述分组以后,发现自身缺少某些条目,就发送链路状态请求分组
4. 目标得到链路状态的请求分组以后,将LSA包裹在链路状态更新分组中并且进行传递
5. 发送者得到这个LSU,更新完自身分组以后,返回一个链路状态确认分组.
经过这五个步骤的反复循环,最终可以得到的解雇哦就是各个路由器的链路状态(LSDB)达到完全的同步, 每隔三十分钟或者链路发生变化的时候,路由器就会洪范发送自己的LSU,确保整个链路是持续有效的.
(下面就是一点小小的补充了)
因为每个路由器之间建立链接关系,这一点在拓扑图中就能看出是一个很庞大的结构,为了避免对于时空资源的过度消耗,在这里我们引入了DR(指定路由器),BDR(备选指定路由器),如图所示
左侧是使用了DR和BDR的OFST协议模式,所有的非指定路由器节点只能和指定路由器之间进行邻居关系的建立,而彼此之间不行.节约了大量的资源.
另外,为了让该协议能更好地适应规模更大的网络,我们喜欢把OSPF划分为多个小的范围,称之为"区域",每个区域都有自己的标识码,其中负责与外界其他自治系统进行交互的主干区域标识为0
这样子划分区域的好处就是,洪泛法会被限制在一个一个的小区域里面,这样保证数据不会过于泛滥
其中的R3,R4,R7被称为区域边界路由器
而R6如果负责和其他自治系统进行交互,则整个被称之为自治系统边界路由器
很好理解对吧
在前面我们主要了解了关于内部网关协议,这两个协议主要使用在自治系统内部,但是对于不同的自治系统之间,我们需要其他协议来实现这些操作.
首先要说明一点,在内部网关协议中,人们习惯性用各种代价来计算最好路径,比如距离,带宽,时间等等.但是在外部网关,或者说自治系统之间这是没有意义的,因为不同的自治系统内部实现的思路不一样,难以用一个统一标准进行衡量.并且在自治系统间进行路由选择的时候还必须要考虑一些安全性问题.
因此在外部网关协议中,寻找"最佳路径"是不现实的,只能说通过多重因素考虑,选择出比较合适,符合用户要求的功能.
在这里我们主要介绍边界网关协议BGP:
在BGP协议中,每个自治系统的管理员都要在AS的边界上设置一个BGP边界路由器,使用这个边界路由器完成多个系统之间的链接,有的时候我们也称呼整个东西为BGP发言人
通过发言人之间交换信息,建立TCP链接,创建BGP对话,最终可以在逻辑上形成一个拓扑网络
两个相邻的BGP发言人被称之为邻站,BGP发言人不仅仅要完成BGP的协议内容,还要完成自己自治系统内部的内部网关协议
这种BGP网关协议特别适用于一些ISP构成的多层网络中,在这里简单举个例子,BSP之间相互告知"通过这条路径可以到达XXXX",如果某个发言人收到了消息,会维护一个"路径向量"的信息,避免环路的产生,并且告知其他自治系统可行的路径
最后补充一下整个东西的四种常用报文
其实整个部分我不想太多说的,因为整个东起其实没啥大问题,在这里就是解释一下最上面说的,为什么转发表和路由表不是一个东西
另外这个图中没有提及的就是,路由器存在一个分组转发的机制,所以是存在输入和输出两个缓冲区的这里需要一点点注意
为了1更有效地提高IP数据报的转发形式和成功机会,网际层使用了忘记控制报文协议ICMP,主机和路由器根据ICMP协议发送差错报告报文和询问报文,这类报文被封装在IP数据报内发送
ICMP报文分成两大类,下面会一一进行解释
差错报告报文一共有以下五种情况:
(1)终点不可达:当主机和路由器无法将数据报文送达的时候,向源头主机发送终点不可达报文
(2)源点抑制:当路由器或者主机因为拥堵等原因而丢弃数据报文的时候,向源头主机发送源点抑制报文
(3)时间超过:当发送的数据报文失去了生存时间以后,就会向源头主机发送时间超过报文
(4)参数问题:简单来说就是路由器检测出了报文有错误,则返回一共参数报文
(5)改变路由:这个有点不太好理解但是好看图,当路由器认为这个数据包应该去另一条路传递的时候,就会丢弃这个数据报,并且告知源主机
询问报文其实很简单,就只有两种
(1)回送请求和回答报文:
其实就两个报文,请求回送,回答,这就是一共正常的应答机制,这种报文一般用来检测是否可以达到目的主机.
一个很简单的应用就是ping指令
(2)时间戳请求和回答:
时间戳请求和回答报文用来请求某个主机返回当前的时间戳,用来同步时间而已
VPN和NAT,到了你们最喜欢的部分了,但是在这里我不教你们....好吧
在座各位估计不少使用过魔法了,但你真的了解这东西嘛
其实VPN是用来在两个专用网络之间架起桥梁用的东西, 其实更多用于一些公司的内部网络,比如公司A在北京有一个专用网络,在上海有一个专用网络, 如果想在这个网络之间进行通信,最简单的办法肯定是拉一条专线:
但是很显然,资金太高了,所以考虑一个问题就是,有没有办法使用公共的互联网资源,来建立一条信道,完成传递.
我知道你们某些人想说虚电路传递,但是这已经是过去的事情了!!!这个行为就像是跨国电话线一样....有用吗>>>并且在逻辑上构成一个更大的,完整的网络的同时,也要保证信息在因特网上传递安全,及时被捕获也不会被破解,更重要的是,专用网内的计算机不能暴露在因特网上!
我们实现的简单逻辑就是, 提供一个IP地址的封装头部,将IP地址分为全球公网和内部网络,在内网内部进行传递的时候,我们使用内网IP地址,在公网上传递,则要转化为公网网络.简单来说,VPN要求在公网上传递数据的时候需要封装一个新的头部*
如图
这里对于传递数据举一个简单的例子
(1)假设H1主机要给H2主机发送数据的时候, 专用网A内的机器先把数据包发送到R1路由器上, 此时数据包中源地址为10.1.0.1, 目的地址为10.2.0.1.
(2)R1收到数据报文以后, 因为这个数据包需要在互联网上进行发送,首先要对数据进行加密,然后重新封装一个头部,这个新的外部头部的源地址和目标地址分别为125.1.2.3和194.4.5.6两个全球公网ip可以放心传送
(3)在到达R2以后,这个临时的首部会被去掉,然后重新解包数据,发送给对应的主机
这个过程也被称作隧道技术,就好像是在一个专用网络上链接一样,因此是虚拟局域网技术,俗称梯子
NAT和VPN虽然在实现思路上有共同的目标,但是实现过程和真正的目标是完全不一样的,这将在后面提及:
NAT诞生的背景仍然是IPv4地址不足,有些组织希望少量个IP能被整个组织公共使用,如图所示
其实有点类似我们之前在AS中提到的BGP发言人,或者说窗口,话事人,现实生活中的代表等等概念.
下面简单解释一下上图中如何发送数据,以及在这个过程中,专用网边界路由器起到什么样的作用:
(1)假设我们的专用网络中的主机192.168.0.2想要往公网中的218.75.230.30发送一个数据报文,将数据打包以后,此时的源地址为H1的地址,目标为H2的地址
(2)数据到达路由器以后, 路由器回将数据报文中的源地址修改为路由器分配的一个IP地址,假设我们临时将1.1.1.1这个公网Ip分配给这个数据包.这个现在数据报文中的源地址就变成了公网的1.1.1.1 , 同时在路由器中需要维护一个临时转化表; 1.1.1.1----192.168.0.2
(3)这个数据包对于公网来说,是没有什么问题的,源地址和目标地址都标准的公网IP,当返回数据包的时候,目标地址现在变成了1.1.1.1,这时候数据包会到达路由器,根据路由器上的临时转化表,将这个公网ip转化为192.168.0.2,这样就可以保证公网和外界的正常交流了
这是NAT的大致转换过程,内部管理系统中需要抱有一定数量的公网IP地址用来固定分配,毕竟这玩应也不便宜,所以管理者希望更进一步节约资金,那么就诞生了结合端口的NAT方案,被称作网络地址和端口号转换NATP
在转化方面是肥肠相似的,区别在于,在封装的运输层PDU中的源端口号修改为一个新的运输层端口号,然后同样是维护一个临时表,记录这样的转化关系.这样子用多个端口号来代替原本的多个IP,路由器只需要一个IP就可以正常工作,把一对多和并发这种压力交给运输层来解决
如图所示
这个部分会在后面的运输层进行解释:D
网络层完结: