![cover](https://img-blog.csdnimg.cn/38ec66bbf1c340888bf90a75aab3f780.png)
计算机网络笔记——网络层、传输层、应用层(方老师408课程)
考研408计算机网络笔记系列文章,总结自方诗虹老师课程+谢希仁《计算机网络第八版》,本文为网络层、传输层、应用层部分。
文章目录
前言
这学期学计算机网络,但是我感觉我们学校的某位任课老师讲的不太行,听完introduction部分以后,我决定脱离学校课程,直接按照408去学习,备战考研。
我购买了408推荐参考教材《计算机网络》,是谢希仁版本的第八版,网上对应的视频不是很多,我找到了方诗虹老师的课程,他用的书就是408的。论及课程质量,虽然方老师的任职学校并不是很好,但是就我的经历来说,408本来就没什么特别深的东西,关键在于能不能讲好,经过我的调查,方老师评价还不错,所以我就直接来听她的课,搭配书籍食用。
本文是系列笔记中的第二篇,内容为网络层、传输层、应用层,按照方老师顺序编写,有一部分顺序因为要加入考研内容,所以做出调整,已经在对应位置注明,基本不会影响随视频阅读。
计算机网络笔记——概述、物理层、链路层(方老师408课程)
计算机网络笔记——网络层、传输层、应用层(方老师408课程)
网络层
最重要的一层,没有之一。
链路层解决了局域网
内部帧
的传输,而网络层的关键任务是将世界上不同的局域网连接在一起,即异构网络之间的连接和资源共享问题,细分为如下方面:
- 跨局域网互联
- 主机标识。如何区分不同主机
- 路由选择。选择哪条道路
- 分组转发。数据如何转发
网络层提供的两种服务
在设计网络层前,关键的问题是网络层到底要实现什么功能?进一步说,就是网络层是否应该负责可靠传输
因为全球互联网络的传输路径太长了,每一个节点都有一定概率出问题,叠加起来难以保证传输质量。因此现在是以不可靠传输为主,可靠传输为辅:
- 少数——网络负责
- 首先建立虚电路逻辑连接,占领资源,沿着这条路进行存储转发,结束后释放资源
- 成本较高,容易出错
- 绝对主流——端系统负责
- 向上层提供简单的灵活地、
无连接的
、尽最大努力交付的数据报服务
- 由主机上运行的传输层协议保证可靠传输
- 向上层提供简单的灵活地、
最开始人们认为分组交换比较好,后面大家觉得为语音、视频服务的电路交换更好,现在随着互联网邮件,web应用的出现,大家又觉得为这种突发流量服务的分组交换更好。
时至今日,分组交换已经占据绝对主流,物理网络也已经定型。改变硬件是很困难的,所以现在的应用程序也都是在适应分组交换网络,不需要保证带宽。
目前使用虚电路网络的只有MPLS和租用专线等,很少,很贵。
网际协议——IP
虚拟互联网络
不同局域网使用的技术不同,无法直接通信。把世界的所有网络技术统一不够现实,也会限制技术发展,不如就使用中间设备转发。
这个中间设备叫路由器,IP协议运行在路由器上。
使用路由器将世界上的局域网连在一起后,就形成了一个虚拟互联网络,即互联网,用户只需要接入互联网,就可以和另一台接入互联网的设备通讯。
网络层其实不止有一个IP协议,而是有三大类:
- 下层协议
- ARP(Address Resolution):负责IP地址和MAC地址的解析转换
- 核心协议
- IP(Internet):网际协议
- 上层辅助协议
- ICMP(Internet Control Message):网际控制报文协议
- IGMP(Internet Group Message):网际组管理协议
下图中,一个信息要经过5跳,前4跳都是交付给路由器,是间接交付。而最后一跳是交付给目标主机,这是直接交付。
IP数据报格式
逐一理解
IP数据报有如下部分:
- 首部
- 固定部分,有20B(5行,为5×4字节=5×32bit)
- 可变部分,最长40B,原因后面说
- 数据部分
接下来逐步解析首部:
- 版本(4):
- 0100代表IPv4
- 0110代表IPv6
- 首部长度(4):
- 范围为5-15
- 实际要×4,即首部长度范围是20-60,且必须是4的倍数
- 区分服务(8):略,不怎么用
- 总长度(16):
- 范围为0-65535。
- 总长度指的是一个完整的IP数据报长度,但是链路层MTU长度会限制这个,所以IP数据报可能被先分片后合并。
- TODO 实际应用中,切分了以后总长度可以超过1500吗?
- 标识(16):
- 来自于同一个IP数据报的IP报文分片的标识相同
- 标志(3):
- 有三位,保留位无意义
- DF=1代表不分片,此时MF位无意义,当DF=0,MF才有意义
- MF=1代表后面还有分片
- 片偏移(13):
- 用来表达报文片的先后顺序
- 偏移=当前片段的第一个bit在原始数据报数据部分中的bit位/8。
- 之所以÷8,是因为标志位占了3bit,为了扩大13位片偏移的表达范围,就弄成8倍。巧合的是,上述计算一定可以整除。
- 生存时间(8):
- TTL,给定初始值,通过一个路由器就-1。
- TTL=64代表最多经过64个路由器,之后再经过路由器就会被丢弃,防止无休止路由浪费资源。
- TTL=0还是可以被主机接收的,只是不能转路由器了
- 协议(8):
- 表示应该交付给上层的哪个协议
- 表示应该交付给上层的哪个协议
- 首部检验和(16):
- 只考虑首部计算的校验码
- 检验流程类似于CRC,但是计算方法不同。
- 源地址(32)。源头IP
- 目的地址(32)。目标IP
- 可选部分功能丰富,但是一般不用,成本较大
整体理解
核心其实就是3个,从哪里来,到哪里去,干什么用。
其他的各种字段都是用来辅助的。
IP数据报分片与长度精算
举个具体的例子。一个ICMP数据报,20B的首部,8B的ICMP首部,3500B的其他数据,所以数据部分为3508B。
以太网MTU=1500字节(以太网帧最大是1518字节,MTU只是其数据部分,即IP数据报),所以假设报头只有20B,则IP数据报片的数据部分最多只有1500-20=1480B
所以3508B切分为3片,bit位为0-1479,1480-2959,2960-3507。
逐部分解析:
- 标志位。分片,所以DF=0。前两个MF=1,代表后面还有片,最后一片MF=0
- 偏移量。1480恰好是8的倍数,我们分片的第一个bit所在的位置恰好是1480的倍数,自然也一定能整除8
注意,之所以前面能刚好成功,是因为MTU=1500,1480B的数据恰好是8的倍数。
但是在21年考研真题里面,MTU换了一下,此时,780B的数据就不是8的倍数了,要向下取整进行对齐,对8取余,把余数剪掉剩下的就是可以被整除的长度了,这里余4,776B就是极限的IP数据部分。
所以切分成3个IP数据报,776+20,776+20,8+20,第二个分片总长度为796(算上报头),后面还有分片,所以MF=1
IP地址
IP地址概述
IP地址和接口
一一对应,不会重复。一般一台电脑只有一个接口,也就只有一个IP地址,但是一个路由器有很多接口,则会有很多IP地址。
IP地址是32位的,人手一个都不够用,更别说一个人有好几台设备了,毕竟当时也没想着给全世界的人用。于是现在诞生了128位的IPv6,号称给地球的每一粒沙子一个IP地址,但是此处我认为,现在的视野还是局限在地球的,万一以后扩展到了宇宙,IPv6还是不够用,还得用新的网络协议。
因为IPv4不够用,所以在管理方面是很严格的。最上面是世界,之后是地区级(RIR),地区下面是国家(NIR),国家下面是ISP(比如移动联通电信)
ISP拿到一批IP,之后根据自己的业务自行分配。
基本的IP地址结构分为两部分,网络号代表了你在哪个局域网,主机号代表了你是这个局域网里的哪个设备。
这种分级结构优点如下:
- 便于管理。IP地址管理机构分配网络号,单位内部分配主机号。
- 减轻路由负担。路由转发是在局域网之间的,因此其负担和网络号数量正相关。主机号的存在将一部分压力分到了局域网内部。
32位2进制太难记,于是切分成4部分记录,即点分十进制记法。每一部分占8bit,所以其范围是0-255。
分类的IP地址——ABCDE
一个地址对应一个局域网,两个局域网是不可以合并的,所以一个IP地址的主机号位数越多,那么其所在的局域网可以容纳的主机数量(IP数量)也就越多,由此根据位数对IP地址分级,通过开头的bit位特殊序列区分类别,A最高,C最低。
除此之外,还有一个1110开头的多播地址,后面会说。1111开头的特殊地址保留备用。
IP地址细节很多,首先要理解固定位以及两类特例:
- 固定位。每一类网络都会固定特殊前缀
- A类固定一位(0),B两位(10),C三位(110)
- 去掉固定的前缀剩余的bit位才是这一类IP网络号的可变部分
- 网络号特例,只存在于A类网络
- 0代表本网络
- 127代表本地软件环回测试
- 主机地址特例,存在于所有网络
- 全0代表本机IP的主机号,即默认值(比如本机是192.168.199.108,那么全0就代表108)
- 全1代表该网络的所有主机,即广播。
由上即可得出下表,括号里是具体计算过程,先解释一下1,4列:
- 考虑固定位计算2次幂,那么A类是8-1=7,B类是16-2=14,C类是24-3=21
- 考虑网络号特例,因为只有A类有,所以A损失了两个网络号,BC类没有损失,直接就是2的n次方
- 考虑主机号特例,ABC类都有,所以就都是先计算2的24,16,8次幂后减2。
再解释2,3列:
刚开始学,可能会认为这三类分法会浪费掉一些网络号,其实不完全是,ABC三类的IP地址的范围是连续的
- A:
0
000 0000到0
111 1111,即0-127 - B:
10
00 0000.0到10
11 1111.255,即128.0到191.255 - C:
110
0 0000.0.0到
110
1 1111.255.255,即192.0.0到223.255.255 - D(多播):
1110
0000.0.0.0到
1110
1111.255.255.255,即224.0.0.0到239.255.255.255 - E(预留):
1111
0000.0.0.0到
1111
1111.255.255.255,即240.0.0.0到255.255.255.255
也就是说,从0.0.0.0到255.255.255.255,这5大类网络的划分理论上是连续的,只不过具体上有一些浪费,浪费在哪里呢?
- 网络号特例:A类地址头尾损失了两个网络号,所以实际范围是1-126
- 主机号特例:ABC类地址每个网络损失了两个主机号
- A类区间是x.0.0.1到x.255.255.254
- B类区间是x.x.0.1到x.x.255.254
- C类区间是x.x.x.1到x.x.x.254
- 多播:其实这不算浪费,2.6亿个多播组并没有那么多。
- E类:预留其实也不算是浪费
所以说到头,实际上没有浪费,只需要知道两个特例让IP地址不完全连续,并且知道断在哪里即可。
分类IP的子网划分
一个网络号里主机号太多,可以划分几个子网出来,便于管理。
简单来说,子网号就是取原来主机号的前m位,因此,m取决于你要分的子网数量。如果是5-8个子网,那么就取m=3
可以看出,子网划分会浪费一些IP地址:
- 子网号特例:
- 一开始子网号不允许全0,全1
- 现在可以,所以子网号特例不浪费
- 不够2的n次幂个子网
- m位子网号对应2的m次幂个子网号,如果要的子网不够这个数量,就会浪费一些子网号
- 主机号特例
- 每个子网内部,主机号都是不允许全0全1的
- 不分子网,其实就是子网数量=1
- 假设子网号m bit,则子网数量为 2 m 2^{m} 2m,则浪费的主机号数量为 2 m × 2 2^m\times 2 2m×2,m越大,浪费的数量指数上升
因为路由器是以网络号转发的,那么可变长度的子网号就是个问题。由此,干脆就制造一个固定长度的子网掩码,网络号部分全1,其他全0,只需要让IP地址与子网掩码进行与运算即可得到网络号+子网号=当前子网的网络地址
如何判断多个IP地址是否在同一个网络?其实就是从子网掩码上下手:
- 子网掩码长度相同
- 网络地址相同
这两个是充要条件,代表两个IP的网络地址位数与值一样,其实就是网络地址完全一样。
不分类的IP地址——CIDR
IPv4分类IP地址便于管理,在前期做出巨大贡献,但是缺点很多,后期逐渐凸显:
- IPv4设计有缺陷,数量不够
- 大地址块(A类)浪费地址
- 大变小浪费:大网络划分子网只是便于管理,并不增加IP地址,反而浪费地址
- 小变大不行:不同网络号之间的网络无法合并
CIDR做了若干改变:
- 合并:网络号和子网号=网络前缀,子网不复存在
- 改名:一个网络前缀对应一个地址块,对应一片局域网
- 斜线记法:子网掩码直接用斜线记法十进制数字表示,比如255.255.1111 0000.0,有20个1则就写20
前缀长度灵活可变,因此地址块大小是任意的,而不是ABCDE这几类大小。其中有三个特殊前缀长:
其中注意31,其实按照规定,主机号是不能全0全1的,但是31比较特殊,就允许这么做了。所以用30替代31也是可以的,30的话,就有4个主机,按规定去除00和11,同样是只剩下两个主机号可用。
总的来说,30和31都可以用,老习惯用30,新规定可以用31。
连续的网络前缀可以合并(路由聚合,构成超网),变成一个更大的局域网,而网络号不可以,两个C类就是两个C类。
下图中,四个25长度的前缀先两两合并,变成两个24长度前缀,再两两合并成一个23前缀。
聚合有什么好处呢?虽然没办法解决IP地址不足的问题,但是可以让网络前缀总量变少,这样就可以减轻路由表的条目数量,提高路由速度。
IP地址总结
- 网络前缀+主机号=IP地址,网络前缀不分等级,只有地址块大小之分
- 一个IP对应一个接口,一条链路两端有两个接口,其IP各不相同
- 局域网内部使用交换机连接,局域网之间只能用路由器连接
- 一个局域网对应一个网络前缀,网里除了和外部打交道的接口,其他接口的IP地址网络前缀必须一样。
- 一个网络前缀可以分多个局域网(用路由器隔离,交换机起不到局域网隔离作用),但是一个局域网内部网络前缀一定一样
- 网络号(网络前缀)不同,则一定代表两个局域网,必须用路由器连接
来个真实的例子:
- 局域网。
- L A N 1 LAN_1 LAN1是一个局域网,其网络前缀是10.0.0.0/24。
- 内部的所有机器网络前缀都是一样的
- 网关。
- 10.0.0.1是 L A N 1 LAN_1 LAN1和外接交流的唯一(有待考证)接口,因此叫“关”。
- 记住,网关这个接口IP也是属于局域网的,所以前缀也要保持一致。
- 网关IP,一般来说,我们习惯于把网关配成局域网的第一个IP,所以主机号往往是1
- 路由器之间的局域网。
- 路由器之间的每对接口都是一个局域网,网络前缀长度是31,代表点对点,用30也行。
- 图中似乎是有一点小问题,网络前缀重复,也可能是我不知道的知识点,有待考证。
IP地址真题考点解析
IP地址考三个考点:首先是ABCDE类IP地址,其次是CIDR,最后就是子网划分。
注意,CIDR中,子网号没有特例,分3位就是8个子网,而网内主机号要去掉两个特例(全0,全1)
出于网络安全考虑,专门划分了一些IP地址专用于局域网,比如10,172,192中的一些IP地址,专用于本地,又叫可重用地址
来真题:
看12年真题,要广播,所以主机号全1,因此子网掩码为0的位,都要置1,不要只置最后一节(那样就会选到C),最终选D
18年真题,就是简单的考一下聚合,4合2合1,选C
19年真题考察变长子网号分配法
,类似于计组里面的指令条数计算,因为这里是2进制的,所以当前位使用0,留出1给下一级用,因此前3级子网号为0,10,110,然后第四级要终止了,所以不留了,全用光,为1110,1111,即4位子网号,剩余地址位8位,于是有254可分配地址,选B
思路拓展一下,如果是6个子网呢?那就要多分一级了,前4级给4个子网号,最后一级用2个子网号,总结一下,k级变长分配,可以制造k+1个子网号。
21年的子网划分考的比较难,但是本质上无非就是两种子网划分方法的情况。观察题干,前三节都是一样的,所以只需要从第4节分析就可以,题干给的网络,第四节为10
- 考虑变长形式,3个子网就分两级,有两种可能
- 作为变长的第一级,即10,110,110分法,即110,111可能是其他子网
- 作为变长的第二级,即0,10,11分法,即0,11可能是其他子网
- 考虑定长形式,无法分出3个子网,给两位就出来4个
- 因此00不行,定长下就得分00,01,10,11,4个子网了
A为0,C为11,D为110,都是可以的,B为00,不可能,所以选B
IP分组的转发
基于终点的转发原理
IP分组经过路由器一跳一跳的转发,转发依据转发表。
转发表基本格式为(目标网络地址,下一跳地址),解释一下这两项:
- 路由器只负责在局域网之间转发,因此只需要关注网络地址,具体转发到哪个主机,由局域网内部转发。
- 下一跳地址
- 下图中,无论是交付给30网络还是经过30网络转交给R2路由器,都要经过接口1,区别在于给30的是直接交付,要转R2的不是直接交付
转发的时候,路由器需要扫描路由表,判断出要转发的目标IP所在的网络地址是什么,找到对应的网络地址就可以转发到下一跳。
关键在于,IP数据报里没有网络前缀长度的信息,因此不可能具体计算出目标IP的网络地址的
回归问题本身,其实转发不需要知道目标网络号具体是多少,只需要知道我要选择转发表里的哪个条目即可,也就是只需要匹配就行,具体你是什么我不用管。
匹配那就简单了,只需要把前缀长度信息记录在转发表里,到时候分别用转发表里的IP和目标IP计算各自的网络前缀,看看是否一样,一样就匹配。
最长前缀匹配
如果使用分类的IP地址,那么两个IP如果掩码不一样,计算出的网络号是不可能一样的,因为掩码不一样就代表类别不同,则前四个bit就不会一样。本质上,是因为不同类别的IP网络号是互斥的,没有交集。
但是CIDR不一样,它不分类,所以一个短的网络前缀(111)完全有可能包含一个长的网络前缀(1110和1111)。此时,一个目标IP,使用不同长度计算出的两个网络前缀,可能会和转发表里的两项同时匹配,匹配的这两个网络前缀必然是一个包含另一个。
既然都已经包含了,那么我们不妨选择最细致的一个网络前缀,就好比送快递地址越细越好,即选择最长的网络前缀,其定位最精确。
下图中,选择26那个。
正因为有这个原则,所以一般在排列转发表条目的时候,是按照前缀长度逆序排列的,这样的话,按序扫描的第一个就是最佳匹配项。
为了加速扫描,还有一个方法就是用唯一网络前缀构造二叉线索树。具体原理还是有点模糊,如果考研要考的话我后面再研究一下TODO。
如果都扫不出来,最后一般会放一个0.0.0.0/0,即默认路由。
按照前缀匹配方式计算,这个条目可以和任意一个IP匹配,也就是默认缺省转发。其实就是,反正已经匹配不到了,就千方百计地把你送出去,说不定别人能把你转到目标位置,尽最大努力。
不过,还有一个特例,即255.255.255.255,这个受限广播IP是不允许通过缺省路由转发的,否则会引起全球的广播风暴。直接广播的IP是可以的,比如2.255.255.255/8
总的来说,转发表大致有四种路由:
- 主机路由。a.b.c.d/32,是人为指定的静态条目,32长度代表着这个条目是朝着某一个具体的IP去的,优先级极高,放最前面。
- 一般的路由。就是我们前面给的那种,在中间。
- 自动的路由。动态路由选择协议自动分配,这个比较复杂。
- 默认路由。0.0.0.0/0,放最后,是无奈之举。
IP地址与MAC地址
路由器通过IP地址转发帧,那MAC地址还有用吗?其实问这个问题前,你应该问,为什么会有IP地址,MAC不也是唯一的吗?
因为IP地址可以通过值来确定是否处于一个局域网,但是MAC地址没有明显的规律,只是唯一,但是不适合路由转发。
但是呢,MAC地址作为链路层的关键技术,是网络层的基础,所以MAC必不可少。总之IP和MAC都必不可少,只是功能不同,IP地址主要用于划分局域网和路由,而MAC地址是在局域网内部使用,用于区分主机的:
具体转发时,首先在网络层封装IP地址,之后在链路层封装MAC地址,发送到另一台机器,向上解封,到网络层处理完后继续向下封装。
从网络层来看,源地址和目标地址都是不变的,因为使用的是IP地址,从链路层来看,原地址和目标地址一直在变,因为机器在变。两者从各自的层次来看,是互不相关的,实际上是在不断转化的。
地址解析协议——ARP
在路由转发过程中,从下往上走很容易,因为只是解包而已。但是从上往下就比较难了,在网络层,我只有下一台机器的IP地址,必须获取其MAC地址才能封装链路层的帧,ARP协议规定了通过IP获取MAC地址
的流程。
ARP有若干情形,下面一一分析:
- 局域网内部的ARP协议。A主机广播询问(B的IP,A的MAC),B接受到后,通过询问报中的MAC地址进行回应(B的IP,B的MAC)
- A主机想通过X路由器给另一个局域网的B主机发信息,即A>X>B,首先AX之间会有一次ARP协议,其次XB之间会有一次ARP协议。
- 主机到路由器的ARP协议。A主机广播询问(B的IP,A的MAC),局域网内无一回应,但是X检查自己的转发表,发现里面有B的IP,虽然A不能直接给B发,但是可以发给X,X代为转发,因此X给A回复(X的IP,X的MAC)
- 路由器到主机的ARP协议。X广播询问(B的IP,X的MAC),局域网内B回应(B的IP,B的MAC)。
实际情况要更加复杂一些,但是不外乎是这三种ARP的组合:
- 局域网内AB主机。AB直接ARP
- 跨一个局域网的AB主机。AX先ARP,之后XB再ARP。
- 跨多个路由器的AB主机。A>X>Y>Z>B,AX先ARP,然后XY再ARP,逐层递归,直到最后ZB建立了ARP。
网络拓扑与转发分析题型(重点)
11年考路由表:
- 目的网络/子网掩码。为了到达所有子网,需要把那两个未达子网的目标网络号进行CIDR聚合,因此得到子网掩码是255.255.255.0(24位),目的网络自然是取前24位,所有答案都是一样的
- 下一跳。是
目标路由器
的输入端IP地址,即~.2
最终选D。对于目标路由器,注意区分下一跳和接口字段,下一跳是目标路由器的IP,而接口字段通常是具体的编号,对应着路由器的出口
15年考最长前缀匹配原则,能匹配上的最长的为C选项。实际上我觉得这道题考的非常没水平,让我考,我就把最长的选项设置为匹配失败的,这才更有考核力度
16年考了一道看起来挺吓人的,仔细分析。
通过网关和子网掩码可以提取出网络号,发现H1,H2在一个局域网,H3和H4在一个局域网。注意,对于IP通信来说,同一个局域网段的(网络号相同),才可以进行链路层通信,因此H1和H2可以通信,H3和H4一定可以通信,所以A和D错。否则必须走网络层路由器,即H1和H3要通信,就得走路由器R2,但是R2上面只给了一个网关,是给H3和H4的网关,因此H1压根就走不了网络层,更别说和H3通信了,所以C是对的。最后,H4可以走网关,因此可以上网,所以B错。
16年又考了一道狠的,还是上面那张图,考察了访问广域网的过程。首先是H3在局域网发出一个分组,然后经过网关的NAT转换,变成路由器R2转发端口的IP,即端口L0的IP,问题来了,这个IP是多少呢?
关键在于长度为30的网络号,已经给定R1为201.1.3.9,在主机号里忽略掉两个特例00和11,剩下的就是01和10,分别对应201.1.3.9和201.1.3.10,R1占了一个9,因此这里的L0只能用10。
最终选D,源IP为NAT转换后的R2的IP,目标IP为服务器的IP。
这道题综合考察了互联网转发过程,NAT,和IP地址,挺好。总之,16年计网的难度是比较高的,几道选择题可以拼一道大题出来了,很行。
18年本质上考的是ARP原理,这道题只是考了其中的MAC地址转换过程,选D
(上图质量不好,实际上应该是有连线的)
22年真题,考网关是什么?首先,网关是一个局域网内部的IP地址,因此网关的网络号就是局域网的网络号(子网掩码同理),其次,网关要连在路由器上,所以用距离本网络最近的路由器的端口当网关,选D
这一部分还会出大题,我放在了408考研大题分析的文章里,移步观看。
网际控制报文协议——ICMP
到现在为止,网络层整体架构已经成形,但是还有一些问题需要解决,完善。
ICMP用于辅助网络层工作,简单来说就是发数据前先确认一下能不能跑通,能再发,不然发一堆路上全没了,浪费。
ICMP报文的格式和种类
ICMP是用于报告网络层状态的,如果出问题,可以让源头知道问题所在。
类型代表了错误的大类。代码代表了大类里具体的问题。
类型值可以分为两类:
- 差错报告报文。单向,路由器反馈给发送方。
- 询问报文。有来有回,发送方询问路由器,路由器再回应。
在差错控制报文内部,分如下几种:
- 终点不可达。因为各种原因导致发不过去,最常见的错误。
- 曾经有一个源点抑制报文,专门用于处理拥塞问题的,通知源点抑制一下窗口,现在废除了
- 时间超过。路由器收到TTL=0的报,无法转发而丢弃
- 参数问题。IP首部出错
- 改变路由。重定向,下次有一条更好的路走
ICMP差错报告报文
什么时候会有ICMP差错报告报文呢?就是当路由器丢弃了一个分组时,就会反向朝发送端回馈一个ICMP。
回馈是在网络层是装在IP数据报的数据部分的,但是ICMP差错报告报文不仅仅只有ICMP的前8字节,还要加上丢了的那个分组的IP报头+数据前8字节。
之所以要加这些辅助信息,是为了帮助源头确定丢的是哪个分组,以便于后面断点续传之类的。
什么时候不发送ICMP差错报文呢?
- 丢失了的IP报文片发送一次,后续报文丢了也不回传了
- 如果ICMP差错报文丢了呢?丢了就丢了,不可能再无限续下去了
- 多播分组不回馈。毕竟很容易丢
- 特殊地址不回馈
ICMP询问报文
- 回送请求和回答。
- 路由器/主机 -> 主机
- 用来测试目标是否可达。
- 时间戳请求和回答。
- 路由器/主机 -> 路由器/主机
- 用来获取目标机器时间戳,用于同步和时间测量。
这个报文比较有趣,是强制回复,因为是协议规定的,只要你收到了,就要回。
ICMP应用举例
差错报文与tracert工具
利用IP数据报中TTL字段,因为是不可能的端口号,所以会一直走,直到目标机器。中途TTL=n的,会在n个路由器被丢弃,回传ICMP报文,这就获取了路由器IP。
理想丰满,现实骨感,路由器也不能让你就这么获取了人家的IP,所以有一些路由器会屏蔽,告诉你请求超时。
回送请求与ping
ping就是典型的回送请求和回答工具。
回送请求可以被利用,针对目标主机实施DDoS攻击,因此可以在主机前面架一个路由器。
协议规定主机接收到回送请求后得回答,又没说路由器得回答,因此路由器一收到了回送请求,就直接丢弃,从而屏蔽发往被保护主机的回送请求。
下一代网络协议——IPV6
IPv6概述
IPv4有大问题
但是协议一旦定下来,就已经无法去改变了,因此只能开发新一代协议,IPv6,这个新的协议需要解决IPv4的问题,同时要对IPv4有兼容能力,逐渐过渡。
IPv6的改进很多,内容如下,可以看完后面回头再看一遍:
这些变化一开始你可能看的一头雾水,但是你后面看完具体的IPv6数据报格式以后,就会理解的更深了。
IPv6数据报格式
IPv6数据报=基本首部+有效载荷(扩展首部+数据部分)
IPv6把IPv4中很多功能都从首部剥离,放到扩展首部里,更加灵活,成本更低。因此扩展首部虽然有首部功能,但是实际是在载荷里。
基本首部
基本首部从IPv4的20字节变成了40字节,但是内容却简短了很多,主要是两个128位(16字节)地址占了大头,其他部分逐一解释:
- 版本(4):0110,即6
- 通信量类(8):如何控制流量呢?其实就是区分优先级,优先极高的能保证流量大。通信量类就是用来标记类别/优先级的
- 流标号(20):
流
指的是一系列IPv6数据报,属于同一个流的数据报流标号一样,在资源预分配的时候很有用。 - 有效载荷长度(16)
- 下一个首部(8):和IPv4中的协议字段一样,代表了收到IPv6数据报后,要送到上层的哪个协议,是UDP,还是TCP,还是ICMP。
- 跳数限制(8):TTL
首部字段数大大减少,因此路由器处理速度很快,转发速度提升了很多。
扩展首部
之所以把一些东西放到扩展首部里,是因为这些东西其实不那么经常用得上。比如分片,其实在IPv6里,分片是发送端预分片的,不到特殊情况干脆就不需要分片,其他也是如此,如果每个数据报都需要检测这些东西,那就有点麻烦了,不如就放进可选里。
注意,一定要按照顺序出现,比如要分片,前面的逐跳和路由就得填上。
IPv6地址
128位,已经大到想不到了。
通信方式多了个任播,就是在周围找个最近的发过去。广播貌似是没有了。
冒号十六进制
128位很长,如果用点分10进制,那么将会很长,因为是8数变3个数,压缩率比较低,因此IPv6用冒号16进制,4数变1数,压缩率更高。
冒号十六进制中,128bit,每个节有4个16进制数,即16bit,因此可以分为8个节。
虽然如此,但是看着还是很长,于是有了一些简化写法:
- 前导0省略。还原的时候,一节内部缺几位就在前面补几个0就行
- 后面的0不行,否则无法还原
- 一段全0压缩。如果一段是4个0,那么可以变成1个0,其实还是前导0省略,只不过得保留一个0
- 为什么不全去掉呢?这个是留给零压缩用的。
- 零压缩。经过1和2压缩后的地址中,如果有若干段连续的0,可以变成两个冒号。
- 零压缩只是压缩段,自然不会考虑尾部的0,比如第一个例子,1080的结尾0就没有被并入。
- 零压缩只能压缩一次,压缩那个最长的0串,否则无法还原
IPv6地址前后缀
正如IPv4的网络地址,类似于CIDR,IPv6也是用斜线记法,但是彻底取消了子网掩码。IPv6和斜线记法一起用还有个好处,就是写网络前缀的时候,可以把后缀零压缩了,很方便。
说到后缀,点分十进制和冒号16进制其实是可以互相转换的,一个16进制段可以转换成2个IPv4段,这种混用经常在IPv4到IPv6的转换中使用:
但是需要注意,IPv4只能是后缀部分。
IPv6的分类
IPv6地址配置方式
前两种是从IPv4继承过来的,新加了一个无状态地址自动配置。凭什么能保证地址独一无二呢?
- 获取局域网前缀。
- 前缀+MAC地址就可以保证独一无二,IPv6太长了,足够装得下这两个东西。
从IPv4到IPv6的过渡
IPv4太广泛了,因此只能慢慢过渡。
双协议栈
DNS通过域名,确认想去的地方是IPv4还是IPv6。
并不是说所有机器都得这么干,只是可以在IPv6和IPv4网络之间,用双协议栈机器转换。
缺点在于,会丢失IPv6的特色信息,比如流标号信息。
隧道技术
针对双协议栈缺点,隧道技术就是要保证数据报的完整。
把IPv6数据报当成IPv4数据报的数据部分来传。
缺点是,徒增成本。
ICMPv6
- IGMP没了。
- ARP也没了,因为既然可以根据MAC地址生成IPv6地址,是不是就可以反过来,从IPv6地址里直接把MAC地址取出来。
实际上,是ICMPv6把这两个吞并了,更加复杂,强大,多了ND协议和MLD协议。
路由选择协议
路由选择协议概述
路由表里的条目很多,人工编辑只能编辑一小部分,更多的是自动通过算法生成的,这个自动生成的过程就是路由选择协议。
换句话说,路由选择协议就是用来发现目标路由,并且找到最佳路径的算法。
路由选择是非常复杂的一个问题,因为一个路由器的选择涉及到其他路由器,涉及到复杂多变的网络环境,而且网络拥塞的时候,很难获得所需的路由选择信息。
各种各样的协议出现,所以需要分个类。
静态策略与动态策略
路由选择协议根据其是否能自适应可以划分为两个种类:
自治系统与层次路由
路由选择协议还有另一种分类方法,是基于层次路由的。下面直接列出,分为IGP(内部网关路由协议)和EGP(外部网关路由协议)但是在具体介绍这些之前,要先讲一下层次路由。
为什么要分层呢?假设不分层,那么网络上主机的规模是很大的,路由表的项目就会很多,而且主机越多,项目也就得随之增加,这很明显不是个办法,因此有两种思路:
- 地址聚合
- CIDR地址可以聚合,但是呢,因为网络地址分配也是随机的,所以实际上很难连在一起
- 实际上很少聚合
- 层次路由
- 是目前的主流解决方法
层次路由的核心思路就是分层,或者说分区。比如下图中,若干路由器,被分成3个大区域,左边大区域内部还可以被分成多个小区域。小区域内部自治,小区域之间互不干扰,大区域统一管理小区域。
实际上,这个区域就叫自治系统(AS,Autonomous System),其有如下特点:
- 自治系统内部有一个管理者
- 自治系统内部整体统一
- 统一路由选择协议,如上图。
- 统一度量参数,比如TTL,带宽,时延
- 自治系统对外各不相同
- 每一个AS有一个全球唯一的AS ID
- 每一个AS对其他AS表现出的是单一且一致的路由选择策略
- 不同AS的路由选择协议可以不同,如上图。
- 自治系统可以继续划分层次。
- 因为自治系统内部协议一致,所以划分出的层次之间协议仍然是一致的,所以算不得是AS,只能说是
私有AS
- 比如中国移动是一个AS,还可以继续划分内蒙古移动,北京移动等,都是私有AS。
- 因为自治系统内部协议一致,所以划分出的层次之间协议仍然是一致的,所以算不得是AS,只能说是
看下面,还是这张图。有三个AS,AS内部可以继续划分私有AS。AS内部IGP统一,自使用各自的IGP,AS之间的IGP可以不同,但是AS之间交流的EGP是要统一的。
层次路由可以解决两个问题:
- 网络扩展性问题:层次路由中,路由表项目可以指向一个区域,至于其他区域里主机数量如何增长,无所谓,路由表项目不会增长
- 管理的自治问题:一个区域内部的网络管理员,可以自由管理其内部成员,而不用被其他管理员影响
总结一下,这些协议都是应用层协议(第一遍看不懂这个总结可以略过)
- IGP
- 最常用RIP,搭配
距离
向量算法,使用UDP - 规模大则用OSPF,搭配链路状态算法,尽可能精简数据,使用IP,直接把数据塞到IP数据报里面,没有UDP报头
- 最常用RIP,搭配
- EGP
- 最常用BGP-4,搭配
路径
向量算法,需要保证稳定,因此使用TCP协议
- 最常用BGP-4,搭配
内部网关协议——RIP
RIP(Routing Information Protocol)是一种分布式的、基于距离向量的路由选择协议。
最大优点是简单,只需要路由器维护从他到其他目标网络的距离纪录即可,路由表条目结构简单(目的网络,距离,下一跳)
,而且两个网络之间只会维护距离最短的那一条路。
什么是距离呢?我们这里的“距离”,指的是从路由器到目标网络的距离,这个距离等于经过的路由器数量+1,如果是直接交付,那么就是0+1=1。
这个也就是RIP中路由器的“跳数”。我们以前学过一个同名概念,但是是从一个主机到另一个主机的跳数=经过路由器的数量。
这两个跳数之间其实是一个东西,比如A>X>B
- 对于X路由器来说,X到B网络是直接交付,X到B的跳数是0+1=1
- 对于A网络来说,A到B经过一个路由器X,跳数是1
所以这两个其实是一个东西,只不过描述的主体不同罢了,补上的那个1其实是路由器自己。
下图中,A经过BE到目标网络的路由器跳数为2(BE)+1=3。左边网络中某个主机到达右边网络的跳数也是3
这个距离有限制,距离为1-15,16就是最大值,代表不可达,类似于编程中的INF值。
距离向量算法
这个算法是迭代算法,一个路由器,最开始只知道和直连网络的距离(1),以一定频率向相邻路由器发送当前路由器记录的距离信息,路由器收到这个距离信息后,会结合自己的距离信息更新路由表。可以看到,这个信息是在网络上逐渐传播的,所以需要时间去迭代收敛。
这个算法每隔30s执行一次,或者是当路由器的拓扑改变,也会马上执行一次。伪代码太抽象,其实挺简单,直接看例子。如下图。
- 一台主机A接收到从C来的RIP报文
- A处理C报文,整体距离+1
- 对比AC报文,进行合并
- 没有新信息:A有C没有,则不变
- 全新信息:A无C有,直接添加
- 重复信息:
- 相同的下一跳,A的下一跳为C(信息来源),则直接替换(因为RIP不允许岔路)
- 出现岔路,即A的下一跳不是C,则两条路选择成本最低的。
RIP的问题在于,他是为ABC类网络设计的,没有掩码这个概念。RIP2做了很多改进,略过。
优缺点
其他的都比较好理解,这里解释下为什么出错后会出现慢收敛,简单说就是套娃,反复传,最后才确认出错。
假定有下面的网络,正确的流程应该是这样的:
- R1发送信息给R2,R2更新到R1的信息表项
- R2发送信息给R1,R1对比后丢弃R2这个项目,收敛。
此处重申,一个表项的含义为(目标网络号,距离,下一跳)
如果网1坏了,正确的流程应该是这样的,:
- R1马上变成(1,16,——)
- R1马上发送消息给R2,R2对比后,更新信息为(1,16,R1),收敛
但是呢,我们不能保证是R1先发送给R2,如果R2先发送给R1,就会出现很大的问题:
- 网络运行一段时间,R2已经收敛为(1,2,R1)
- 网络1坏了,R1马上变成(1,16,——),马上就要准备发送错误报告了,此时R2恰好发送信息给R1,打断R1发送
- R1对比信息(1,16,——)和信息(1,2+1),发现目标冲突,即更新为(1,3,R2)
- R1这个时候才能给R2发送信息(1,3),此时已经晚了,循环往复开始。
- R2对比信息(1,2,R1)和信息(1,3+1),因为R1就是来源,所以直接替换为(1,4,R1)
- R2发送信息(1,4)
- R1对比信息(1,3,R2)和信息(1,4+1),因为R2就是信息来源,所以直接替换为(1,5,R2)
- 如此循环
- 直到16为止,每次都要等30s,所以这几轮得等个大概8分钟才能发现错误,太久了。
这里还有一道16年的真题,考察了这个原理。
R1,R2此时都为(目标网络,2,R3),R3为(目标网络,16,-),题目告诉你,R3只向R2通告了,R1是不受影响的,所以R2会先变成(目标网络,16,-),之后又会收到R1的通告,变成(目标网络,2+1,R1),此后就是满收敛的过程了,选B,没有继续深入考了。
这道题的关键在于,R3只向R2通告,而题目说的R2更新,是包括R3,R1各自通告一次后的结果,如果只考虑R3那一次,就会选C,其实还有一次R1呢,这是命题人的目的,人家考的就是这个“坏消息传的慢的原理”,所以必然要出现一次坏消息被覆盖的过程
内部网关协议——OSPF
RIP太简单,容易出问题,而且不适应越来越复杂的网络,OSPF是为了克服RIP的问题做出来的。
RIP中,衡量距离的是跳数,但是现在的网络容易拥堵,跳数太过粗暴,就好比是堵车了绕道反而更快。
OSPF本质上仍然是路由选择协议,只要是这个协议,原理一定是指定一个开销的指标,选择开销最小的那条路。
与RIP相比,OSPF的指标更加复杂,维护的信息也更加全面,维护过程更加繁琐。
链路状态
首先就是,OSPF如何衡量链路是否优质?这个就是其记录的链路状态:
- 相邻关系。本路由器和哪些路由器相邻
- 链路质量。相邻路由器之间,链路的质量如何
- 费用
- 距离,时延
- 带宽
这些信息被记录在链路状态数据库(LSDB,link state data base)中,在频繁的链路状态信息交换过程中,所有路由器的LSDB逐渐丰富并且统一。
本质上来说,LSDB就是区域内的路由器拓扑结构图,即每个路由器拥有当前区域内全部的路由器地图。
维护过程
维护过程类似于RIP,就是一个路由器向其他路由器发送链路状态信息,美其名曰洪泛。
- 洪泛距离可以是256,很远,比RIP的16大多了。
- 洪泛的信息即当前路由器
相邻
的所有路由器的链路状态 - 只有链路状态
改变
的时候才会洪泛。以可靠
的洪泛法(带ACK的)向全网更新链路信息。当然每个一段时间也会更新一下链路状态。
理论上这些东西差不多就够了,但是我们还要进一步细化。
邻居关系并不是连在一起那么简单,是有一个构建过程的,过程中需要用到5类信息:问候信息,数据库信息,链路状态信息。
在OSPF收敛过程中,路由器要和周边路由器建立邻居关系:
- 邻居关系只需要用hello报文维护。
- 完全邻接关系需要在邻居的基础上,充分交换信息,统一后,才能算完全邻接关系。
全流程如下:
- 邻居关系构建
- 对于一个路由器,通过HELLO问候文组发现周围邻居
- 进一步设置metric=成本,储存在数据库中
- 洪泛
- 路由器:简要描述,发送DD(Description)数据库
描述
分组,发送一个简化版的数据库给邻居 - 邻居:对比反馈,如果有更新的条目,则通过LSR(Request)链路状态
请求
分组,反馈给路由器,表示邻居需要更新 - 路由器:发送具体更新条目,以LSU(Update)链路状态
更新
分组的形式发送 - 邻居:更新反馈,把条目更新后反馈一个ack,以LSAck(Ack)链路状态
确认
分组的形式反馈
- 路由器:简要描述,发送DD(Description)数据库
补充一下:
- 2过程是一个一石激起千层浪的过程,以一个路由器为中心,其DD可以顺着网络蔓延到整个自治系统,这个过程成本比较大,所以OSPF主要在链路状态变化时洪泛,当然也可以一定时间间隔再发送,只是间隔更长
- 每个路由器都储存了整个AS的地图,因此可以使用Dijkstrea算法构建路径,但是路由表只存下一跳的信息
分区
可以看到,LSDB应该是一个很大的数据库,如果路由器数量太多,LSDB会很大,所以OSPF使用层次划分区域。
OSPF的AS分区,主干区域是核心,其他分支之间互不沟通,每个区域有个32位编号,主干是0.0.0.0,其他的依次增加,看起来像IP,实际没啥关系。
分区后的OSPF路由器种类如下:
- 主干区域内路由器BR(backbone router)。主干区里所有路由器。
- 常规BR。位于主干区内部
- 区域边界路由器ABR(area border router)。位于主干区边界,与其他区域连接的路由器
- 自治系统边界路由器ASBR(AS border router)。位于主干区边界,用于与外界AS交流的路由器
- 普通区域里的路由器。
分区域以后,洪泛只限制在一个区域内,同步统一以后,再告诉骨干区,再转交其他区域。
外部网关协议——BGP
BGP协议是AS之间通信的协议,力求选择一条从一个AS到另一个AS的路径,路径比较好但是不要求最好,毕竟这太复杂了。
BGP通信的对象
BGP采用的是路径向量(Path Vector)的路由选择协议,分为两个子协议:
- eBGP:AS之间。eBGP连接两个发言者(speaker),这两个发言者路由器负责AS之间的BGP通信。
- iBGP:AS内部。和IGP的区别在于,其只传递BGP信息。
BGP协议的通信仅限于经过发言者,从外到内和从内到外。如果想让内部的一个路由器经过发言者到达另一个发言者,这是不允许的,是一种浪费。
BGP通信的内容
说到头,BGP到底传递的是什么信息呢?BGP的目标就是找一条路径,因此其信息就是路径:
【前缀(目的网络),路径,下一跳路由器接口】
其中这个路径是可以拼接的。下图给出3个路径:
- 第一个路径是AS3发给AS2的,AS3告诉AS2,你可以通过IP3a,通过AS3这个路径到达X。
- 第二个路径是AS2发给AS1的,AS2告诉AS1,你可以通过IP2a,通过AS2-AS3这个路径到达X
- 第三个路径类似于第一个。
由此可见,路径信息其实是随着传播而逐渐变长的。当多条路径同时出现,按照如下策略选择,其中AS跳数也在考虑之中。
此外,一条路由还不能出现兜圈子现象,这也是资源的浪费。检测也很简单,当一个路由器(比如AS3),收到的BGP信息的AS-PATH字段中出现了自己,说明自己就在环上,这个路由不能要。
在这种前提下,你就可以知道,AS-PATH中不可能出现重复的AS号了。
路由器工作原理
我们前面讲路由器的转发,那个其实只是路由器下层的功能。实际上路由器分为上下两层:
- 控制层面。
- 传输控制信息
- 根据路由选择协议协同计算出
路由表
- 软件计算,秒级
- 数据层面。
- 传输具体数据
- 根据
转发表
转发IP数据报 - 硬件计算,纳秒级,和控制层面差了9个数量级,很离谱。
具体来说,路由表和转发表不完全是一个东西。
- 核心路由表是上层通过各种协议+静态路由+直连路由生成的,给人看的,条目就是(源地址,目的地址,接口)
- 转发表(FIB)是基于核心路由表形成的硬件级别的表,可读性很差,还附带了很多其他信息,但是计算速度快。
再具体来说一下转发过程。总的来说就是:
- 链路层接收,解封
- 校验
- 提取IP信息,查转发表
- 修改IP数据报TTL和校验和字段
- 封装,链路层发送
中间如果校验失败,查询失败,都会丢弃,所以网络层并不可靠。
最后插播一点额外的知识,家用路由器其实和企业路由器大不相同。
我们学的是企业路由器,而家用路由器实际上不是路由器,其最基本的路由功能简单极了,只需要送到一个目标口(静态路由),压根就没有动态路由协议,真正的功能是下面一大堆附加的。
IP多播
以前就只有单播,广播,IP多播就是将IP报定向发送给目标的一组主机,可以看到没有IP数据报被浪费。多播的应用场景很多,本质上就是一对多。
多播地址与分组
多播地址用D类地址,为[224,240),一个多播地址就是一个多播组。
此外,还有硬件地址(00-00-5E-xx-xx-xx),与多播IP一一对应。
如何将一些主机放到一个多播组里呢?在IPv4网络中使用网际组管理协议(IGMP,Internet Group Management Protocol)
首先,R1-R4都是多播路由器,其记录了多播信息,比如自己局域网的某些主机在某某多播组里。这个信息通过两个IGMP报文更新:
- 主机加入多播组
- 路由器定期询问主机是否还在多播组(心跳)
IGMPv1是标准,其他的都只是建议标准。
多播路由
多播路由比单播更加复杂。实际上就是要找出以源主机为根节点的多播转发树,数据报就沿着树发送就可以,每分支就复制一次。
多播树
多播树是类似于STP,采用一定算法生成的。
如果树上的节点发生变化,要进行对应的剪枝和嫁接。说白了就是没主机了就剪掉路由,有新主机就把路上的路由器加进树里。
此外,有一些网络不支持多播,所以只能通过隧道技术包装多播数据报,等到达另一个支持多播的网络里再次传播。
因此,隧道也可以理解为在多播树上的一条比较长的不分支的路径。
洪泛传播
给定一个确定的多波束,数据报采用洪泛的方式沿着多播路由树发送,可能会有兜圈子或者绕远路现象。因此采用反向路径广播RPB(Reverse Path Broadcasting)策略来控制。
假设R已经知道了最优路径,而最优路径就代表最快,所以在组播中,从最优路径传过来的包一定是最先到的。反过来说,只要是从其他路径过来的,就一定是排在最优路径后面的,已经重复了。
下图中③就是对这两种情况的处理,最先到的(最优)就向子节点转发,其他的都是重复的,不转发。
基于核心的发现技术
密集分布是我们前面学的常规场景。多播的发送者一定是服务器,对每一个发送者(对应一个多播组)构建一颗源点树。
如果多播组的成员分布的非常零散,那么为这一个组单独弄一个多播树,就有点浪费资源,树上的路由器负载太低。
于是稀疏分布的情况下,多个多播组公用一个核心树,让这颗核心树的负载提升到一个合理的程度。
VPN和NAT
VPN(虚拟专用网络)
首先要知道,PN是什么。其实我们前面说的局域网,就是专用网络,专用网络是物理上用线缆连接的一个局域网。
而VPN上的设备不一定用线缆连接,只需要他们都连接在公网上,就可以构成一个虚拟的局域网。之所以需要VPN,原因如下:
- PN太贵
- 直接用公网不安全
如何做到VPN呢?下图中,部门A和B没有直接连在一起,而是通过公网连在一起,但是属于一个VPN。
在部门AB内部,IP是私有的,如果要做到在公网上通信,需要将私有IP转换为公网IP。为了保证公网上的安全,需要进行隧道加密。
隧道具体来说就是把一个VPN里的两个私有地址加密封装到数据部分里,然后用R1和R2的共网IP光明正大地传播,不用担心VPN内部数据被窃取。
NAT(网络地址转换)
世界上的IP数量有限,对于一个物理局域网,其内部的主机是没有公网IP,只能共享一个对外的公网IP,通过路由器交流。
这个将私有地址转换为公网IP,再从公网IP转回去的过程,就是NAT。
从私有地址转换为公网地址很简单,但是公网地址怎么转回私有地址是个问题,假如有两个私有地址都从这一个口出去,那转回去的时候该怎么办呢。
一种解决办法是一一对应,即一个公有地址同时只对应一个私有地址,也就是说,如果只有一个公有地址,那么专有网络里的主机只能轮换使用这一个公有IP。总之一个公有IP同时只对应一个私有IP。
这种方式需要频繁更换转换表项。
另一种方法是NAPT(Network Address and Port Translation)。NAPT相比于NAT技术来说,可以让多太主机同时使用一个公网IP。这似乎破坏了一一对应的原则,实则不然,NAPT还多了一个Port字段,维持住了一一对应。
具体是将TCP端口号作为Port,和网络层的IP混用。Port字段是放在IP数据报的数据部分的。
NAT是可以节省IP,但是会破坏网络层的完整性。
VPN和NAT的区分
NAT和VPN虽然都有地址转换,但是本质上完全不同,切莫混淆。
NAT是物理意义上的,将私有地址与公网IP进行转换的。
而VPN虽然也会进行转换,但是这个转换只是附带的,或者说是基于NAT的,VPN真正的作用是让两个局域网通过公网构成一个虚拟局域网,是利用公网扩展局域网的技术。
多协议标记交换MPLS
MPLS原理
路由表会随着网络的变大而变大,查表成本会越来越大。而且查表太久,会把缓存填满,分组更容易丢失。
所以需要解决的就是查表速度太慢。MPLS应运而生,这是一个建议标准,所以只有一部分设备支持,技术点如下:
标签凭什么能缩减路由表呢?以前,每一个目标网络必然对应一个路由表项,实际上很多目标网络的转发接口是一样的,那么这几个网络的路由表项实际上是可以合并到一起的,构成一个标签。由此,标签实现了路由表项的多合一,简化数量,自然就加快了转发。
如何实现:
- 首先要有一个MPLS域,因为MPLS只是个建议标准
- 其次,当IP数据报进入MPLS域,会在IP数据外面打上标签,再进行链路层转发
- 最后,出MPLS域后再去掉标签
可以看出,标签介于链路层首部和IP首部之间,所以MPLS其实是介于2-3层之间的,MPLS不仅仅可以减少路由表项目,减少查表时间,而且还可以把转发放到链路层,少了解包和封装的过程,也可以节省不少时间。
MPLS报文结构
MPLS首部介于2-3层,知道这个就行。
软件定义网络SDN
集中式思想
注意SDN这个考点,22年新加入考研,细化了。
SDN是2009年才提出的,是很新的东西。
在传统的5层结构中,每一层各司其职,但是实际上每一层都有类似的功能,都是查表,转发。而且还有一个重大的问题,就是分布式的协议又复杂又慢,其实用集中式的控制也不是不可以,或许会更好,这就是SDN的初衷。
SDN实际上是把各层(链路,网络,传输层)的查表功能抽离出来,做成几个上层的功能模块,用于控制,比如路由选择,接入控制,负载均衡。
控制模块生成统一的转发表,下放给下层的转发机,转发机器是统一的,统称交换机。
至于如何上层对下层的控制,其实门道就在转发表里,转发表不一样,下层的逻辑就不同,自然就实现了控制。
SDN控制层在中间,向上把北向接口提供给程序员,进行软件的设计,向下把南向接口提供给硬件设备,至于如何兼容,就要靠Openflow之类的南向接口协议了。22年真题考的就是南向接口,那么如果要继续考,无非就是流表本身或者北向接口了。
SDN的思想还有一个好处就在于,以前路由器的技术只掌握在少数厂家手里,一台路由器集成了控制层面,数据层面,协议的实现,现在分离了,能让更多的软件开发商参与进来。
OpenFlow
来看看SDN目前主流的协议OpenFlow的具体实现。
在以前,我们每一层都有一个转发表,比如链路层有mac表,网络层有路由表,传输层应该也有某个表(还没学到)。我们如果用5层网络架构去说,那在每一层都得去查表,最后转发。而OpenFlow,把三个表变成三个流表,放到一起,进行集中匹配,匹配后进行对应操作(可能是转发,丢弃)
听起来很抽象,总之给我的感觉就是把中间三层合一了。可以看到,同时匹配3层的字段,然后进行综合了中间3层的更复杂的操作。这看起来不符合解耦的思路,让这个匹配过程压力很大,但是实际上在上层控制模块的作用下,匹配过程也可以做到很快,这就是SDN有潜力的一个点,整体更快。
传输层
概述
传输层要解决两个问题:
- 网络层只是从一个主机到另一个主机,没有区分数据是从哪个应用来的,要去哪个应用。
- 网络层没有做到可靠传输。
传输层也是很重要的,和网络层一样承上启下,如下图,下接通信,上接应用。因此,传输层是保证数据稳定性的最后一个关口,所以会尽可能提供不同程度的稳定性保证,但是此时就无法保证延迟,带宽了。
进程之间的通信
进程通信
从程序员角度说,网络通信其实是进程通信。
通信分为三个步骤:
- 复用:应用层的多个进程把数据交给一个传输层协议
- 传输层协议进行数据传输
- 分用:传输层协议把数据交给目标的多个进程
传输层提供的服务
具体到传输层的服务,其提供基本的服务和扩展的服务。
基本的服务仅仅是简单扩展网络层,是最低限度的,对应UDP协议:
- 提供进程到进程的通信
- 提供报头+数据的全面差错检测
- 链路层检测仅仅可以检查帧内比特差错
- 网络层仅仅检测IP报头的差错
传输层的增强服务用于保证可靠传输,丰富且复杂,对应TCP协议:
- 保证可靠传输
- 提供传输过程中的控制
- 流量控制
- 拥塞控制
传输层的两个重要标准
- UDP,面向无连接
- 端口灵活,一对多多对一,服务灵活
- 只提供基本检验
- 数据单位:UDP报文/用户数据报
- TCP,面向连接
- 必须保证端口一对一,不提供广播,多播服务
- 保证全双工可靠传输
- 数据单位:TCP报文段
传输层端口
进程是比较复杂的,不同系统和不同系统都是不一样的,所以传输层选择把这些东西丢给应用层,然后再应用层和传输层之间抽象出一个界面,端口就是进程号和传输层之间的界面,进程和端口绑定由应用和操作系统来解决,而传输层只交付端口。
端口很像接口,其实本质上是一个东西,只是在软件上习惯叫端口,硬件叫接口,便于区分。
端口是16位的,只具有本地意义,是用于区分本计算机上的不同进程的,和其他计算机没关系。类型有3种,如下图:
到此为止,通过IP:PORT套接字,就可以实现在互联网上找到一台主机的一个进程。
用户数据报协议——UDP
UDP概述
前面已经大概介绍了一点,直接来UDP特点:
- 无连接。
- 直接发送,不用建立连接
- 尽最大努力交付
- 只实现传输层基本功能:进程通信+差错检测
- 面向报文。
- 一次性发送/交付一整个报文,至于网络层怎么切分,不管。
- 报文长度应该由程序员定义好,太长就会分片,降低IP层效率,太长了数据比例就低,也降低IP层效率
- 没有拥塞控制
- 不论网络状况如何,使劲发
- 好处在于实时性高,坏处是不稳定
- 服务灵活
- 单播多播广播都可以
- 首部开销小
- 8字节
UDP的特点:
- 稳定性差
- 速度快,延迟低
- 服务灵活
UDP首部
很精简,8字节报头:
- 源端口。理论上发送是不需要源端口的,但是可能用于回信
- 目的端口。如果目标网络的端口没有应用程序,那么就会用ICMP返回一个“端口不可达”
- 长度。指整体长度,其最小值是8
- 校验和=校验算法(伪首部,UDP首部,UDP数据)。其中伪首部是12字节的临时数据,用于让校验和更加有用,只是在计算和验证的时候加上,实际传输不需要。
传输控制协议——TCP
TCP概述
TCP特点:
- 面向连接的
- TCP是软件层面的,协议保证的逻辑可靠传输
- 类似的还有物理层的电路交换,网络层的虚电路交换。
- 只能点对点传输
- 流水线式的可靠的传输
- 采用确认,编号,重传的技术实现
- 全双工。
- 收发数据使用两个不同的缓存
- 面向字节流
- 不同TCP报文是连续流式发送的,因此报文边界的信息不能靠TCP的发送和中断来表示,而是应该把边界信息放在字节流里面,技术很多,暂不叙述。
TCP首部
20个字节的固定长度,和IP数据报的固定长度一样:
- 端口号。各占两个字节
- 序号
- TCP是字节流传输,可以看做字节数组,编号就是数组下标
- 字节流上面有多个TCP报文,对应多个TCP报头,每个TCP报头里,序号字段记录了当前报文中数据在第几个字节。
- 确认号ack
- 不用于发送,而是用于反馈
- 设ack=x,则代表我已经收到了你前x-1号的字节,你下一次发送期望从x号开始
- 同一个TCP报里的确认号和序号没啥关系,A给B发的确认号,是B下次给A发的序号
- 数据偏移
- 数据开始处相对于TCP报头开始的偏移,其实就是首部长度
- 单位为4
- 保留
- 标志位
- URG:1代表紧急,高优先级
- ACK:1代表ack字段启用。其实只有最开始这一位才是0,其他情况都需要确认
- PSH:1代表不用等缓存满了再发。一般是紧急或者后面没数据了
- RST:1代表要重连,发生了严重错误
- SYN:1代表用于TCP最开始的请求链接或者回应连接。当SYN=1,ACK=0,是请求,SYN=1,ACK=1,是回应。
- FIN:1代表已经发送完了,发送方已经断连,接收方可以释放连接了
- 窗口
- 用于反馈
- 告诉对方,我现在的接收窗口容量还有多少,这是动态变化的
- 检验和
- 类似于UDP,只是其中代表协议类型的字段变了
- 紧急指针
- URG=1才有用
- 指出TCP报文段中,紧急数据的末尾位置
- 可选项和填充。
- 可选最长40字节,填充要保证报头是4字节的整数倍
在可选字段中,有一些其他概念:
- MSS,这个和MTU其实是一类概念
- MTU:链路层中,数据的最大长度,为1500
- MSS:传输层TCP协议中,规定的数据最大长度。应该尽可能大,但是不要让IP层分片
- 如下图
- 窗口扩大(window scale)。
- 如果窗口字段不够用,可以分配n个bit,则窗口值扩大 2 n 2^n 2n倍。
- 时间戳
- 10字节
- 可以用于计算RTT
- 也可以用于在序号字段溢出变回小值的时候区分新报文段(时间戳新)和迟到很久的旧报文段(时间戳旧)
- 选择确认(SACK)
- 最初TCP使用累计确认,丢了就得把窗口全部重传
- 改进后,允许SACK字段指出缺失的具体字节,选择性重传对应字节
可靠传输的原理
如何在不可靠传输的基础上实现可靠传输呢?那必然是高强度的检验机制+流量控制。
停等协议
直接给出可能的情况:
-
正常情况:
- A发送,超时计时器启动
- B接收,回送ACK
- A在计时器触发前收到ACK
-
分组错误或分组丢失:
- A发送,超时计时器启动
- B没接收:分组丢在路上,或者B检查有误,丢弃
- A的计时器触发,重传
- B收到
-
确认丢失和确认迟到:
-
确认丢失
- 计时器只对发送生效,不对ACK生效,ACK只反馈一次,丢了就丢了
- A计时器触发后,再次发送分组
- B收到重复分组,丢弃,但是还是会再次反馈ACK
-
确认迟到
- A重发
- B收到了重复的分组,丢弃分组,但是仍然反馈ACK
- A收到了重复的ACK,丢弃ACK
-
再给出概括:
看下图,停等协议的效率取决于斜率,斜率由RTT决定,传的越慢,停等的效率就越低。
连续ARQ协议——GBN协议
解决停等协议低效率的方式就是流水线,干脆就不等了。因此必然更容易出现问题,所以需要更多的保障措施。
可靠传输协议采用滑动窗口的方式去收发,是全双工的,我们仅从单工角度去解释,实际可以做到双工。
- 正常发送
- 一个循环的内容:
- A一次性把窗口内的所有分组都发送了,比如0-5
- B全部接收,返回一个累计确认ACK,不一定是6,假设是ACK(4),代表0-3都已接受
- A接收ACK(4),把窗口滑动到4的位置
- 如此往复,只要窗口滑动一下,就会有一些未发送的分组进入了窗口,在循环的开始被发送出去
- 一个循环的内容:
- 超时重传
- A发送的每一个分组都有一个单独的计时器
- 当A的N号分组计时器触发,则会重发所有已发送但是未被确认的帧,看似是GBN,实际上这个N只是代表最大重传的帧数,实际重传几个,要看有几个是发送了但是未被确认的。
- B即使收到了正确的2456帧,只要3没了,456也得丢掉。
GBN是比较粗糙的流水线协议,因为其接受窗口大小=1,如果经常回退,会造成重大浪费,还不如停等。
选择重传协议——SR协议
GBN有明显缺陷,就是回退的浪费有点大,所以自然而然就想到,能不能只重传超时的一个分组?
SR协议做出如下改变:
- 接收窗口=发送窗口
- 累计确认变成单个确认,发送方只重传超时的一个,不会重传一整个窗口
- 接收方来者不拒
- 当接收方的前k个分组连在一起,才向上交付并且滑动,否则就不交付
- 因为接受窗口大小=发送窗口大小,所以一定能保证缓存发送窗口发送的所有包,不可能出现死锁
- 举个反例:假设接受窗口<发送窗口,发送窗口卡在了0-9,接受窗口卡在0-8,发送方不断发送0和9,其实接受方只是在等0,但是因为窗口不够,收不到9。可见,两个窗口大小相等可以保证分组不被浪费
看起来SR协议是要比GBN好很多,但是还是有一点小的缺陷,其实GBN和SR是各有千秋:
- SR协议因为每个分组要单独ACK,所以ACK数量是要大于GBN的。
- GBN因为回退,重发的分组数量要更多
- SR是一个中庸可靠的协议,以稳定少量的浪费换取整体的稳定,而GBN敢于冒险,只是翻车了消耗比较大。如果网络好,很少出现回退,那么GBN效率更高,如果经常出错,SR更好
TCP可靠传输的实现
以字节为单位的滑动窗口
TCP的缓冲区可以理解为字节数组。滑动窗口是缓冲区上面的一片区域,因此TCP传输的最小单位是字节。
注意,这只是最小单位,实际上可以一次性发送100个字节的数据,封装到一个TCP报文段中,然后若干个TCP报文按照流水线方式发送。
TCP协议采取等大窗口+累计确认+回退N的方式:
- 发送窗口=接受窗口。
- 发送窗口内部分为已发送未确认的和可用窗口。
- 接收窗口可以乱序缓存。
- 发送方关键字段:序号seq,确认号x,窗口w。
- 序号表明发送方发送了某个序号的数据过来。
- 确认号和窗口对发送方没啥用
- 接受方关键字段:ACK=1,确认号,窗口
- ACK=1代表反馈
- 确认号表明接收方累计确认了x-1个数据,期望收到x数据
- 窗口用于流量控制,这个字段是目前的接收窗口大小,发送方会根据这个字段调整发送窗口大小
- 实际上,发送方的窗口起始值=发送方接收到的ACK反馈值
具体滑动的过程,就是和我们前面的ARQ类似,区别有两点:
- 等大接收窗口可以乱序缓存了
- 接受窗口随着计算机的状态调整,发送窗口大小会随着接收方的反馈进行调整
超时重传时间的选择
超时重传是一个合理的策略,但是这个时间如何确定呢?
- 太短:引发不必要重传
- 太长:丢包空闲期太长
这很难,因为网络情况很复杂,而且有波动,如果只有一个固定的超时重传时间,不太行,应该有一个算法去实时更新。
RTO标准更新算法
直接给公式:
R T O = R T T S + 4 × R T T D RTO=RTT_S+4\times RTT_D RTO=RTTS+4×RTTD
RTO由两项求和而得。 R T T S RTT_S RTTS代表RTT的平均值, R T T D RTT_D RTTD代表RTT波动的平均值。所以RTO其实就是在RTT均值的基础上考虑到了网络波动容错,RTO要总是略大于RTT。
具体看,这两项平均值都是滑动加权平均。其实这和机器学习思路很像, α \alpha α实际上就是个学习率。推荐的 R T T S RTT_S RTTS学习率是0.125,而 R T T D RTT_D RTTD是0.25,这表明我们对波动要更加敏感,因为波动本身就是一个瞬息万变的东西。
在传输的过程中,RTO的更新流程如下:
- 每一次往返都可以得到一个 R T T i RTT_i RTTi,
- 计算新的 R T T D RTT_D RTTD
- 计算新的 R T T S RTT_S RTTS
为什么要先计算新的加权偏差呢?因为偏差就是新旧的差异嘛,所以要新-旧。如果先计算新的RTT,那么就是新-新了,不合理。
Karn算法与RTO修正
因为TCP有超时重传机制,所以TCP确认存在二义性:
- 发送方原始数据和重传数据seq一样
- 发送方无法确认反馈的ACK是针对哪个数据的,这就是二义性
既然无法确定,那就一刀切,只要发生重传,就干脆不采样这次的RTT值。
新的问题又来了,原始Karn算法面对网络巨变导致的RTT骤增,会出现无法更新的bug。
如果真的是因为网络巨变,导致RTT大大增加,那么此后的包一定都会重传,按照Karn算法,这些重传RTT都不去采样,RTT就不会更新了。因此,即使是重传不采样RTT了,也要对RTO进行一定的变化,这就是修正的Karn算法:
RTO更新总结
- 正常发送(不重传),那就按照RTO标准更新算法来, R T O = R T T S + R T T D RTO=RTT_S+RTT_D RTO=RTTS+RTTD
- 重传时,按照修正的Karn算法来,直接加倍, R T O = γ × R T O RTO=\gamma\times RTO RTO=γ×RTO
一般情况下,RTO基本稳定,出现网络巨变就会触发Karn算法,RTO骤增,等网络巨变真正过去以后,RTO算法又会根据标准更新方法逐渐回落。
选择确认SACK
我们前面说了,虽然TCP报文是以字节为单位计数的,但是通常一个TCP报文里面是放了很多数据的(最多1500-20-20=1460B),若干TCP报文采用流水线方式发送。
那么问题来了,如果使用GBN算法,一旦一个TCP报文出问题,就要重传N个TCP报文,这个负担是很大的,如果能只选择性重传一个TCP报文就行,这就是我们前面的SR算法。
当然,TCP还是比较特殊的,特殊就特殊在虽然是以字节为单位,但是实际是以TCP报文(字节段)为单位的。
如果按我们以前的SR算法,我每发送一个数据,都要回传一个ACK,这个ACK是单独确认的,可是问题来了,如果只是利用ACK里面的确认号字段,这一个字段无法确认字节段的两个边界的。
所以TCP只能增加一个SACK可选字段,用来报告左右边界。不过没有绝对的好事情,SACK字段是可选字段,会增加报头负担,效率是否提高是个未知数。
可靠传输题型总结
在题目中,要区分ACK和ack:ACK是标记,用于表示是否是反馈,而ack是确认号
此外,还有人纠结于ack到底是多一位还是正好,实际上普遍是ack多一位,比如收到了100,那么就反馈一个ack(101),这样比较方便,发送方直接把窗口起始位置调成ack的值就可以,非常直观。后面你看到方老师给的图,基本都是这样。
注意区分,题目给出“收到x号帧的确认”,这是一种文字性描述,代表已经收到了x,但是如果是“ack=x”,那么实际上只代表收到了x-1
传输过程分析
窗口大小限制
首先明确,帧号(数据下标)默认从0开始,比如2bit编号,数据号就是0,1,2,3,而窗口大小,确实就是长度,从1开始
GBN和SR是统一看的,凡是采用窗口协议,nbit编码,那么两方窗口之和≤ 2 n 2^n 2n
GBN协议中,接收至少=1,那么发送端窗口尺寸最大 2 n − 1 2^n-1 2n−1
考虑SR协议,两方窗口要相等才最好,因此单方窗口最大是 2 n − 1 2^{n-1} 2n−1,最佳也应该是这个值。
举个极端的例子证明为什么窗口总和最大为 2 n 2^n 2n,以n=3举例,如果发送方窗口大小为8(此时已经有危险),那么最多同时发0-7,此时0号帧就会有歧义:
- 如果确认帧正常,下一个0代表有效帧
- 确认帧丢失,那么0代表重传的帧
关键是接收方无法确定确认帧是否丢失,所以窗口大小要让出一个来,不可以是 2 n 2^n 2n
这题秒杀了,总和为8,因此选B
信道利用率(超高频考点)
算信道利用率,本质上,是单个周期内,发送数据的时间占整个周期的比例(剩余的时间就是空闲时间)
停等协议最好计算,一个周期=发送一个帧+RTT
GBN协议和SR本质上是流水线,因此需要让流水线跑满才能保证信道利用率最大(反之,退化为停等)
此时就要考虑传播时延,你要保证在一帧的整个周期内
,数据帧发送是不间断的,即一个窗口的传输时间≥周期
,左右同乘数据率,则一个窗口的数据量≥一个周期内的最大数据传送量
以12年举例。
首先,桢长度不确定,取最小的极限情况,原因是如果帧更大,那么发送的数据量绝对满足流水线要求,但是反过来就不一定了,帧变小会导致窗口的数据量缩水,不见得可以满足。
假定一个帧为128B,则发送时间为64ms,注意,接收方的ACK也需要64ms,所以实际上一个完整的周期为64+2×270+64=668ms,有的题目中ack不耗时,这需要你区分一下。
用668/64=10.4,因此至少要11个帧,因此就要4bit编码
在看14年,先算一帧周期,这题的ack是不计长度的,所以T=0.08ms+2×50ms,约等于100ms,此时一个窗口的数据量为8Mb<10Mb的周期极限数据量,就知道跑不满流水线,此时效率为80%,因此实际速率是80Mb/s
15年,本质一样,你先算极限情况下一个周期可以发多少帧,单帧62.5ms,一个周期有9个帧,然后用效率卡一下是7.2个帧,也就是说至少8个帧,注意陷阱,GBN窗口大小限制
是
2
n
−
1
2^n-1
2n−1,所以最后是4bit编码
18年更简单,停等,设未知数套公式,信道利用率=传输时间/一帧周期
20年把确认帧改为1000B,因此周期公式要变长一点,所以周期是2000ms,但是注意,ACK虽然也是传输时延,但是并不是数据的传输时延,因此真正的数据发送时间只有800ms,结果为40%
TCP的流量控制
为什么要流量控制?
因为接收方的接受能力有限,所以在负担大的时候,应该减少流量。
如何实现?窗口大小协商
利用滑动窗口实现流量控制
在TCP报头中,有一个窗口大小字段,这个字段是接收方的接收窗口大小,代表了接收方的接受能力,反馈给发送方后,发送方会将发送窗口大小变成这个字段的值(实际上会有一个放大倍数,参考TCP扩展报头中的窗口扩大字段)
直接看例子,发送方始终以流水线方式发送TCP报文段,直到可用窗口=0。接收方在反馈ACK的时候,也会带上rwnd字段,通知发送方及时修改发送窗口大小。
从下图中可以看出,如果接收方想少来点数据,就返回一个小的rwnd,如果不想接受,就返回一个0值rwnd。这就实现了从接收方的角度控制流量。
当然,这个控制也有缺陷,因为从接收方调整接收窗口大小到发送方收到新的窗口大小之间有一段0.5×RTT的时间间隔,这个时间段内可能又会发出更多的数据,这一部分接收方没法接受,也就可能浪费了。
0窗口死锁
当rwnd=0,那么发送方之后就不会发送数据了。同时,接收方因为没有收到数据,也不会反馈数据报,也就不会反馈新的rwnd,这就是一个死锁局:
- 发送方等待接收方的反馈,才能调整rwnd
- 接收方等待发送方发送新数据,才能反馈新的rwnd
为了解决这个死锁,使用持续计时器。
- 当rwnd=0,发送方会启动计时器
- 超时后,会发送一个探测报文。
- 探测报文数据只有1B
- 数据是上次发送的数据的最后一个字节,而不是新的数据。
- 接收方一定会接收,并且反馈rwnd。
- 如果还是0,发送方重新计时
- 如果不是0,则打破死锁
TCP的传输效率与Naggle算法
前面讨论了rwnd=0的情况,还有一种不好的情况,是rwnd太小,比如1。
每次TCP发送报文段,那么长的报头,结果数据只有1,效率极低,所以如何处理rwnd太小的情况呢?
直观的思路是等接收方的rwnd变大再一次性发送。
TCP发送报文的时机
在思考如何让TCP等待之前,先了解TCP什么时候会发送:
- 溢出MSS会自然发送
- 应用层强制PSH=1
- 特殊计时器。比如持续计时器
Nagle算法
nagle算法适用于糊涂窗口综合征,此时接收方接受能力有限,发送方只能一点一点发送。
采用Nagle算法的接收方,会根据数据选择是否反馈ACK。
接收方如果收到的数据太少,而且接收方自己负载很高,则接收方不会反馈ACK,此时发送方因为收不到ACK,也就不会继续发送了。
在等待的时间内,发送方数据会逐渐积攒,接收方的接受能力也会逐渐恢复,等到发送方觉得可以发了(实际上不一定),发送方才发。
TCP的拥塞控制
拥塞控制的一般原理
定义拥塞
:网络整体上多处同时拥堵,而且这个时候负荷越大,吞吐量越小。拥塞本身很复杂,还会正反馈加剧拥塞。
表现
:分组延迟增大,吞吐量下降,甚至瘫痪
起因
:用户对资源的总需求>网络可用资源(节点缓存,链路容量,处理机能力)
增加资源有用吗?有点用,但不多。如果只增加一部分资源,那么就会把压力转嫁到其他资源上,可能反而会令网络更坏(把其他资源直接压崩了)。如果是整体增加资源,也没用,因为用户对于网络资源的需求是无限的,后面还是会拥堵。
关键在于,约束用户的发送量,即拥塞控制。
拥塞控制
是针对整个网络进行的发送量控制,在空间和时间上都非常复杂,是个动态问题,所以很难办,而且很多时候就是拥塞控制本身引发了网络恶化。
如果没有拥塞控制,吞吐量会在后期走下坡路。一个理想的拥塞控制,可以让网络的吞吐量随着负载逐渐增加,最后稳定在一个最好的状态。实际上的拥塞控制介于两者之间,可以让这个下坡路来的更晚,而且也可以在跌落之后更快的恢复。
拥塞控制有两种方式:
- 开环控制:设计网络之初,就考虑周全,力求不拥塞,但是运行起来以后不可以调整了。
- 闭环控制:实时监测,发现拥塞后及时控制拥塞
- 发现拥塞。分组丢弃增加,这是最主要的指标。其他指标都和这个有很大的关系。需要注意,分组丢弃只是征兆,并不是原因,原因是很复杂的
- 控制拥塞。通知源站,源站根据拥塞控制策略调节流量。
TCP拥塞控制机制
TCP拥塞控制采用CWND(拥塞窗口)控制发送速率。
这个CWND和前面流量控制的RWND平级,代表要发送的数据量。后面会详细对比两者之间的相互作用关系。
拥塞控制中,速率公式如下:
r a t e = c w n d R T T B y t e s / s e c rate=\dfrac{cwnd}{RTT} Bytes/sec rate=RTTcwndBytes/sec
直观理解,当cwnd大,RTT小时,rate会很大。这是因为cwnd大,代表要发送的数据攒的够多了,所以就要快点发。RTT小,代表网络环境不错,那么也可以快点发,快上加快。
拥塞控制其实就是控制这个cwnd来间接控制rate
- 如果没有拥塞,就把cwnd变大,快点发,提高利用率。
- 如果出现拥塞,就把cwnd减小,减少注入网络的分组,缓解拥塞。
发送方判断拥塞
- 超时重传计时器超时。
- 代表网络出现严重拥塞,交付能力很差
- 举例:发送1234,过去很久,一个ACK都没有,超时计时器直接超时
- 可能因为传输差错会导致丢包,但是全丢了的概率很小,所以就认为是网络延迟太大了。
- 收到三个重复的确认。
- 代表网络可能拥塞,但是还有一定交付能力
- 举例:发送1234,4个包,1号包没了,在超时计时器计时的窗口期内,234号送到,接收方连续返回三个ACK(1)
拥塞控制算法
- 慢开始(slow-start):指数增长,直到达到基本预期值
- 拥塞避免(congestion avoidance):线性增长,从基本预期值慢慢爬升
- 快重传(fast retransmit):快速重传
- 快恢复(fast recovery):腰斩+拥塞避免
慢开始
- 思想:从小到大,逐渐给网络增加负荷,希望一开始强度尽量低,但是又希望快速探出底线,达到基本预期,所以应该用指数增长。
- 时机:cwnd跌落谷底时,比如刚启动或者出现拥塞后。
- 细节:按照指数规则增长cwnd大小。
- 从1开始,每往返一轮就翻倍,重传不算。比如,轮次1是从1到2,轮次2是从2到4,以此类推。
- 如果cwnd>ssthresh,慢开始的目标就达到了,可以终止了。
- 如果出现丢包,那说明这个时候代表强度已经够大了,而且预期不够合理,应当调整预期,重新开始慢开始算法。
慢开始门限(ss-thresh)
:防止cwnd增长过大导致拥塞。ssthresh代表了慢开始的基本预期,或者说是慢开始的目标。
之所以用ssthresh,是因为指数增长是比较危险的,越到后面,增长量就越大,有可能因为一次性增长量过大,直接把网络压瘫痪,所以不要等那个时候再停止,应该是到达一个阈值就提前停止。
- 当cwnd>ssthresh,即使没有发现丢包也要提前停止慢开始。
- 当cwnd=ssthresh,就看个人选择了,如果害怕风险,就终止,激进一点就再翻倍一次。
假设发生了拥塞,要先进行一些处理才能进行慢开始:
- ssthresh=max(cwnd/2,2)
- 因为cwnd会出现拥塞,说明要降低cwnd预期,即把ssthresh变成原来的一半。
- 最少是2,ssthresh至少得大于cwnd(1)
- cwnd=1
- 拥塞已经发生,应该偃旗息鼓,等待网络好起来。
- 执行慢开始
拥塞避免
- 思想:让cwnd慢慢增大,试探出网络负荷最后的底线
- 时机:已经具备一定规模时,比如慢开始刚结束,或者快恢复刚结束。
- 细节:
- 具体就是线性增长
- 轮次1,从1到2,轮次2,从2到3,以此类推
- 因为长得慢,所以不需要提前终止。
快重传
- 思想:有拥塞趋势的时候(在连续收到三个重复ACK时),立刻重传。否则就会出现超时计时器超时,如果只是因为一个分组的小错误而误判拥塞,采取过激反应就太亏了。
- 时机:连收到续三个重复ACK
- 措施:
- 发送方立刻重传
- 接收方接受后立刻返回ACK,以最快速度结束这个分组的超时计时器。
快恢复
- 思想:连续收到三个ACK,确实代表有拥塞的趋势,但是又不能一棒子打死,所以就先退一步,然后再慢慢前进。
- 时机:连续三个重复ACK,快重传执行后马上执行快恢复
- 细节:
- ssthresh=cwnd/2。有拥塞趋势代表cwnd不合理,那就把预期下调为一半
- cwnd=ssthresh(下调后)。和出现严重拥塞不同,我们只是把cwnd下调一半,并不直接跌到1,毕竟还没拥塞。
- 执行拥塞避免算法(线性增长)
所以说,拥塞+慢开始=跌倒了快速追赶,3ACK+快重传+快恢复=踉跄了一下后慢速恢复
拥塞控制过程解析
这个图看着还是挺复杂的,其实没啥可怕的,整体可以说是一个AIMD过程,Additive Increase Multiplicative Decrease,无非就是增长和下调
- 增长:
- 慢开始。跌落谷底或者刚启动时,都要慢开始
- 拥塞避免。慢开始过ssthresh后,或者腰斩调整后需要恢复时,使用拥塞避免。
- 下调——统一将ssthresh腰斩
- 严重拥塞。此时务必从头开始,cwnd=1
- 3ACK,此时不是特别严重,cwnd=ssthresh
整体过程:
- 整体保持增长势头
- 如果是慢开始,则会逐渐过渡到拥塞避免
- 拥塞避免无异常情况则会一直保持
- 出现意外会下调,并且进行恢复
- 严重拥塞。下调预期后,直接跌落谷底,执行慢开始快速追赶,再过渡到拥塞避免状态
- 3ACK。快重传,下调预期后直接从ssthresh执行拥塞避免缓慢恢复
来看个例子。
- ssthresh=16,cwnd=1,慢开始快速增长
- cwnd=ssthresh=16后,进入拥塞避免,线性增长
- cwnd=24时,超时,调整ssthresh=12,cwnd=1
- 慢开始快速增长到cwnd=12,进行拥塞避免,线性增长
- cwnd=16时,3ACK,快重传+快恢复,调整ssthresh=8,cwnd=8
- 执行拥塞避免,继续线性增长
其实还是很简单的,就是往上爬,出意外就退,然后继续爬。
此外还需要考虑一个细节,cwnd在慢开始过程中是指数增长的,但是ssthresh并不一定是指数级,比如ss=12,但是cwnd原来是8,下一轮到底是从16开始进入拥塞避免还是从12呢?
很显然,是12,符合直觉,所以拥塞避免算法的开端必然是ssthresh
再论下调,无论是拥塞还是3ACK,都代表ssthresh不合理,通通要腰斩。区别仅在于cwnd,拥塞下调的彻底,直接归1,慢开始,而3ACK要跳过慢开始,直接拥塞避免,因此从ssthresh开始,即cwnd=ssthresh(下调后的)
拥塞控制vs流量控制
流量控制和拥塞控制,都是在控制发送流量,只是其源头不同。流量控制受制于接收方接受能力,由接收方通知发送方,而拥塞控制受制于网络拥塞状况,需要发送方自行判断。
前面提到了cwnd和rwnd是平级的,具体关系其实是两者共同决定了发送窗口的上限。因为发送方发送数据要考虑到通路是否通常(是否拥塞),也要考虑目的地是否有足够的接受能力(接收窗口),二者构成水桶效应。
主动队列管理AQM
其实拥塞控制已经讲完了,其中拥塞判断是根据丢包来判断的。路由器本身是有丢包策略的,这个会影响到TCP的拥塞控制,AQM是一种理论上可行实际不咋地的丢包策略。
路由器默认的丢包策略是尾部丢弃,一旦超过最大队列长度,后面进入的包全部会被丢弃。
当路由器队列长度变大,出现尾部丢弃,此时会丢弃连续若干的分组,此时就会触发超时,让发送方跌回慢启动状态。也就是说,队列满=拥塞=超时
如果只是一台主机这样,也就罢了,如果是多台主机呢?如果出现路由器队列排满的情况,那么他们基本会同时超时,然后同时进入慢启动,同时重传。
重传并不可怕,可怕的是同时,这就会导致拥塞,然后拥塞导致同时重传,重传再导致拥塞。
我们可以从“同时”下手,只要这些主机不是同时重传,这个问题就没了,因为主机是用丢包判断拥塞的,所以只要随机丢包,就不容易同时判断拥塞,也就不会出现同时重传的问题。
我们将以前的最大队列长度变成最大门限,将最大门限分成两个区域,前面的区域是一定不被丢弃的,后面的,来得越晚越容易被丢弃,如此打乱丢弃顺序,就有可能缓解同时判断为拥塞的问题。
然而实际上AQM没啥大用,现在也有很多其他方法,但是核心思路就是让路由器通过对分组的排队进行智能管理,也承担一部分解决拥塞的责任。
TCP的运输连接管理
TCP是面向连接的,所以肯定是分成三个阶段:
链接是全双工可靠的,所以这个过程的管理还是有点复杂的。
TCP连接建立——三次握手
连接建立的作用:
- 互相知道对方的存在
- 协商参数,分配资源,准备传输数据
连接前,服务器应该处于监听状态,此后由客户(client)向服务器(server)主动发起请求,分为三步:
- 请求连接。SYN=1,ACK=0,不带数据,消耗序号
- 响应连接。SYN=1,ACK=1,不带数据,消耗序号
- 最后确认。SYN=0,ACK=1,若带数据则消耗序号
总结:前两个连接报文的SYN=1,三个报文中,除了第一次ACK=0,其他都是ACK=1。
TCP连接释放——四次挥手
因为是全双工传输,所以释放连接要释放两个方向的链接,因此更复杂一些。
建立连接后,双方是同级的,任何一方都可以主动释放连接。假设A要先释放连接:
- A通知B释放。FIN=1,ACK=0,可不带数据,但是一定消耗序号
- B响应,ACK=1
- A收到响应后,连接处于半关闭状态,A不会主动向B发送数据,B可以主动发送。
- B通知A释放。FIN=1,ACK=1。
- 其实算响应,是因为ACK=1,算是回复报文。
- A响应。ACK=1
- 虽然此前是半关闭状态,但是A仍然有回应能力
- A响应后会保持一个
时间等待计时器
,超时后才会彻底断开。 - 假设A立即关闭,且响应丢包,那么B就会一直以为A没有收到断连通知(3),不停地重传断连通知。有了计时器以后,可以保证A的响应传到B后,A再关闭。
总结:断连通知的FIN=1,4个分组中,除了第一次ACK=0,其他都是ACK=1。
保活计时器
前面说的是正常的连接和断开,如果过程中客户死机了,又或者客户应用程序只是占用链接而不发送数据,浪费服务器资源呢?此时就需要服务器去主动断开。
保活计时器运行在服务器上,2小时内没有收到客户的信息,就进行探测。发送10个探测报文,间隔75s,此时会有两种可能:
- 有ACK,则证明只是占用,根据策略进行处理
- 没ACK,说明客户死机了,直接单方面中断连接
TCP有限状态机
最后给出状态机,很复杂,看看得了。
UDP/TCP综合考点分析
前面说,TCP是面向字节流传输的,但是却是封装在数据报这个整体里面的,所以到底怎么传输的?
在窗口控制中,数据是以字节为单位的,比如一轮发送半个窗口的数据,而这些数据要传输,必然是要封装TCP报头的,如果1B数据就要一个TCP报头,很显然不合理,因此实际上是把一轮数据封装到TCP报头的,也就是一个TCP段。
所以这两者不冲突,在逻辑上面向字节流,指的是窗口单位是字节,而一轮GBN可以发送很多数据,这些数据被一次性打包到TCP报文里了,实现上是按照报文ack的。
再提一嘴段长
的概念,其实就是有效载荷,最大段长和MSS字段一致
TCP首部字段细节计算
发送方seq,段长与反馈方ack的关系:
seq代表发送的第一个字节的下标,因此本段最后一个字节的下标为seq+段长-1
,因为ack要下一段的第一个字节,因此要再加一,正好和-1抵消,因此ack=seq+段长,所以ack=发送方下一个段的第一字节,这种设定是非常优秀的,计算很简洁,如果选择题碰上了考的很细节的,不确定请务必画个图分析一下下标到底差多少。
09年真题,累计确认,因此直接加起来,选D
11年真题,画图可得,1段的确认号=2段的seq,直接用3段seq-2段长度,选B
13年真题,新的seq=收到的ack,即2046,而反馈的ack=收到的seq+段长,因此是2013,注意不要算成2014(如果真考出来可能就会有一批人错),选B
TCP建立连接/断开细节
我们默认都是消耗序号的。
三次握手中,前两次必然消耗序号,最经典的考法就是考两侧的seq和ack。
前两次握手比较简单,考法单一。进阶一点还会考第三次握手。
假如第一次握手用的是seq,关键在于,第三次握手如果不带数据,就不会消耗序号,这句话其实有更深层次的统一性:如果你第三次握手不带数据,那么不消耗序号,发送第一个数据的时候,seq=seq+1,如果第三次握手带数据,则消耗序号,实际上你发送第一段数据的时候的seq也是seq+1,也就是说,无论你是否选择在第三次握手带数据,反正你在建立TCP链接后第一次发数据的seq一定是第一次握手的seq+1
在现实中,TCP名义上是3次握手,实际上只有两次,第三次直接就用来传数据了,这也就是TCP建立链接只需要1个RTT而不是1.5个RTT的原因。
看20年真题,你无需管他到底第三次握手带不带数据,反正第一次发数据的seq=1000+1=1001,所以最后总数据=5000-1001+1=4000B,选C
4次挥手中,可以分为两波,每一波都是先FIN=1,后FIN=0,代表着通知与反馈。此后AB之间只能进行单向数据传送,也正因此,B传给A的ack是不变的,因为A已经不再发送数据,也无法给B反馈。
还会考C/S端的状态变化细节,还是那张图:
- 第一次挥手,C发出FIN后变成FIN_WAIT-1
- 第二次挥手,S发出ack后变成CLOSE-WAIT,C收到ack后变成FIN-WAIT-2,此时S还可以向C端单向传输数据
- 第三次挥手,S发出FIN后变为LAST-ACK,C收到FIN后,变成TIME-WAIT
- 第四次挥手,C在TIME-WAIT状态中,每隔一段时间都发送一次ack,直到一个设定的时间间隔(2MSL,两倍最长报文段寿命)后才撤掉,这样几乎能100%保证S收到ack(虽然不能完全保证)
21年真题,直接秒了,三次挥手后C变成TIME-WAIT,选B,送分。
22年真题,考了2MSL的细节知识点,最短时间的条件是2,3次挥手无间隔,也就是说S端的close-wait时间段掐没了
TCP拥塞控制
其实前面讲的过程已经很详细了,这里再稍微多点做题细节
首先需要明白cwnd变化的时机,就是在收到ack的一瞬间就变化
以09年真题为例,第4个RTT···收到应答时
,也就是说,这一瞬间cwnd已经变化了,所以在8的基础上线性增1即可,即9
其次注意发送窗口,拥塞窗口,接受窗口三者的关系。
如14年真题,一看题干就是考你拥塞控制+两窗口取最小,拥塞控制结果为cwnd=12,但是rwnd=10,所以取10,选A
15年真题打烟雾弹,首先是拥塞控制初始阈值,其实就是ssthresh,然后还有一个接受窗口的隐含条件,即接收方有一个缓存,这个缓存剩余的空间就是反馈的rwnd,因为缓存数据没有被取走,所以rwnd是一直在减少的,cwnd又在增加,因此这道题考的绕了个弯,最后还是考这俩窗口的关系,最后rwnd=1,cwnd=16,取1,选A
注意“最快”,“最慢”的表述,有的题不告诉你ssthresh,让你求到达一个wnd的时间,比如17年是最快,所以慢开始,而20年是最慢,所以直接用拥塞避免线性增长
总之,只需要理解这个AMID过程的细节和思想就可以应对各种题型。
校验和报头总结
- 链路层帧校验和,校验内容和首部
- 网络层校验和,仅校验首部
- 因为网络层传输内容基本不变,所以校验首部最高效
- 传输层UDP校验和,校验内容和首部
- 需要添加伪首部,形成一个涵盖了网络层和传输层两层首部的伪首部
应用层
应用层基于传输层,向用户提供服务。应用层的协议很多,都是针对某个具体而广泛的应用而设计的,目标就是用于协同不同主机上不同应用之间的通信。
本章具体内容多且杂,比较实用,重在理解。
域名系统——DNS
DNS(Domain Name System)域名系统。
DNS概述
域名和IP地址一一对应,这样的好处在于,把不好记的IP地址变成了好记的域名,而且后续更换IP地址,域名也可以保持不变。
DNS负责将域名转换为IP地址,你想一下,全球这么多IP,域名也是很多的,同时这种转换也是很频繁的,所以DNS也是一个比较复杂的东西,关键在于降低压力。
具体的做法是采用分级域名+分级域名服务器
互联网的域名结构
下面给出一些常见域名。有一些注意点:
- 不同级别的域名,可能出现重名。比如org可以是顶级域名,也可以是二级域名。
- 教育,政府,军事,如果作为顶级域名,只能是美国的,由此可见霸权。
域名服务器
我们的域名现在是树状结构了,那么理论上,只需要逐级管理,就可以大大减轻管理机构的负担。
事实也是如此,管理机构就是域名服务器,上级域名服务器记录了其管理的下层域名-IP的对应关系。
域名服务器有如下4个类型,域名服务器本身也是服务器,也有IP和域名:
- 根域名服务器
- 管理所有顶级域名
- 从a.rootservers.net到m.rootservers.net
- 有13套装置,但是不止13个机器(几百个,遍布全球)
- 顶级域名服务器
- 管理旗下二级域名
- 权限域名服务器
- 管理一个区的域名
- 本地域名服务器(默认域名服务器)
- 不管理域名,是用来代理主机发起DNS解析请求的
- 一个机构,比如ISP,大学,或者大学的系都可以有一个本地域名服务器。
- 这么做有利于提升效率,保证安全,在DNS解析过程中具体介绍。
DNS解析过程
首先声明,无论本地域名服务器采用迭代查询还是递归查询,最开始的主机对本地域名服务器的请求都是递归查询。
我们先看本地域名服务器的迭代查询
- 主机向本地域名服务器发起DNS请求。
- 本地域名服务器逐级迭代询问
- 在域名解析的时候,本地先询问根,然后根给出顶级服务器的IP,然后本地再去问顶级,顶级再给出权限服务器的IP,之后本地再去问权限,权限给出目标域名的真正IP
- 此时压力集中在本地域名服务器上
- 本地域名服务器拿到目标域名的IP后,返回给主机
为什么非要走本地域名服务器呢?似乎直接由主机发起迭代查询也可以。
实际上,本地域名服务器可以理解为一种缓存。本地域名服务器在进行一次DNS解析后,会把(域名,IP)元组保存起来,等下一次DNS查询域名时,直接返回。
之所以这么做,是因为本地域名服务器对应一个机构,其内部的成员访问的域名应该有很大的重合,这么做可以极大的减少冗余查询,减轻域名服务器的压力,同时加快用户查询速度。
其实还有一种递归查询
之所以少用,是因为这样是把本地域名服务器的压力分摊到其他服务器上了。实际上这些压力应该给本地域名服务器。
DNS协议例题
需要区分1+4级机构:
- 用户
- 服务器
- 本地
- 根
- 顶级
- 权限
16年真题,问的是域名服务器的DNS查询,因此用户那一次请求不算,从本地服务器算起,因此最少是0,最多的话,分了4段就是就是4次,选C
具体过程为,先从根得到com的IP,然后从com得到xyz的IP,然后从xyz得到abc的IP,然后abc得到www的IP,此时已经结束DNS解析,下一次就可以可以直接访问www的IP了。
20年真题结合了HTTP协议考察上网过程,该过程包括了DNS解析+数据传输(TCP建立连接+网页数据传输),后者需要2个RTT,DNS解析访问互联网最小(仅局域网内部)和最大时间分别是0和3个RTT,因此选D
还需要再辨析一下TCP建立连接的消耗时间,从TCP三次握手过程来看,乍一看TCP建立连接要1.5个RTT,但是你要知道第三次握手是可以带数据的,也就是说第三次握手本身已经相当于开始与服务器进行交互了,所以第三次握手完全可以和http请求绑定在一起,从这个角度来看,建立TCP链接实际上只需要1个RTT,因此从建立连接到获取数据其实是2个RTT
文件传输协议——FTP
FTP概述
把数据从一个主机送到另一个主机是很简单的,但是如果两台主机的系统不一样,那如果只是单纯传输一样的bit位,很有可能文件在另一端会完全失效。
FTP的目的是为了消除文件传输过程中可能出现的不兼容型。
FTP基本工作原理
FTP采取CS架构。
- 服务器先打开21号端口,启动
主进程
监听请求 - 客户请求传输
- 服务器监听到后,并行地执行两个操作
- 启动
从属进程
,绑定20号端口,进行数据传输 - 服务器继续监听其他主机的传输请求
- 启动
用两个端口区分主进程和从属进程,可以保证有条不紊,主进程负责控制,从属进程负责具体的传输。
实际山,FTP具体有两种模式:
- 协议,无论是控制还是数据,都用TCP链接
- 端口,控制端口是服务器的21,数据端口不一定,用x,y表示任一端口
- PORT模式(默认,主动模式),服务器开放20端口,服务器主动连接客户端的x端口
- PASV模式(被动模式),服务器开放y端口,客户端用x端口链接y端口,也就是说,PASV模式下,数据端口完全就是协商而来的
- 注:PORT和PASV的主动/被动是针对服务器的
远程终端协议——TELNET
TELNET是远程终端协议,客户把鼠标和键盘的信息传给服务器,服务器把画面回传。鉴于客户端和服务器端的操作系统不一样,TELNET同样是用一个中间格式来进行传输。
TELNET虽然是有登录机制的,但是是明文传输,不安全。所以现在多是搭配SSH之类的东西进行远程登录,我们现在计算机实验室训练模型跑实验常用ssh来远程操作。
万维网——WWW
万维网、URL、资源
www是一个访问全球资源网络的协议。
我们很容易把域名和www混为一谈,因为我们平时上网似乎都是输www.xxx,实际上域名与主机对应,URL对应主机上的资源。
上图给出URL的一般格式,其中:<端口>这个字段不一定有。
说白了,一般情况下一个URL里面一定会包含一个域名,因为我们上网本质上就是访问其他主机的资源的,默认的资源是index.html,也就是所谓的主页。
我们平时看似是直接输入域名,实际上浏览器给我们补上了协议(http://),补上了www.,补上了/index.html。实际上还是用http协议+URL去访问的。
怎么才能在主机上看到其他主机的资源呢?我们通过浏览器来观看。为了便于浏览器显示,以html作为资源的主要形态,html内部可以嵌入各种文件,也可以通过网络下载到本地后再打开。
URL一般来说都是指向html的,html内部可以嵌入超链接,于是无数的html之间就构成一张大网,这就是所谓的万维网。
http协议
URL告诉我们目标资源在哪里,而从目标主机取回资源的过程就是http协议。
其中注意get方法,除了返回数据以外,还会返回状态码。我们平时常见404not found,不过这些仅供参考,到底哪里出问题其实不好说。
最开始的http/1.0协议是无状态
的:每次传输报文都会建立和释放一次tcp链接。
这么做一来是比较浪费资源,二来是不利于动态网页。于是有了http/1.1,这个协议支持长连接和流水线传输。
http/2.0是对1.1的一个增强。
https=http+SSL+TLS,实现了http的加密传输,多用于支付等私密场景。
代理服务器与cookie
类似于本地域名服务器,www也有代理服务器,又称万维网高速缓存(www cache),可以把URL-资源缓存起来。
尤其是校园网,用代理服务器效果会很好,这也是校园网流量便宜的原因,这么多学生访问的网站都大差不差的。
代理服务器可以缓存服务器的东西,服务器也可以缓存客户的信息,这就是cookie。
cookie与用户一一对应,你之所以可以不用登录就直接上一个网站,其实是服务器已经把你的cookie记住了,看到你这个cookie就知道你已经登陆过了。
又比如购物车,你这个cookie加了一堆东西进购物车,下次你登录网页后,购物车里的东西还在,也是因为cookie。
http协议例题
区分http不同版本的交互流程,做题的时候要明确版本号:
- 1.0,非持久链接,建立,发送,断开
- 1.1,默认持久链接,建立,发送多个(默认是流水线)再断开
- 1.1也可以选择非持久链接,用close标识
- 2.0,加密版本的1.1
HTTP报文分析,注意如下字段:
- Host:目标主机
- Connection:连接方式,Close代表非持续链接(发完就关闭,close),keep-alive是持续连接
- Cookie,是服务器分配给用户的唯一标识,用户第一次被响应后会保存cookie以便下次免登录身份识别,有Cookie代表访问过
从http协议开始,已经可以从头到脚把网络走一遍了:
- 浏览器访问万维网URL
- DNS请求,获取目标服务器IP地址
- DNS基于传输层UDP协议
- DNS请求的过程要熟悉
- 进行应用层HTTP协议的访问
- HTTP基于传输层TCP链接,要先建立连接再传数据
- 还要注意HTTP的版本号
- 要注意可靠传输过程中的传输机制与拥塞控制
- 在23过程中,整体网络是基于网络层-链路层-物理层的层层转换发送的,需要不断地拆包封装
- 网络层转发用路由表(以及硬件转发表)
- 网络层-链路层,用IP地址获取MAC地址要用到ARP协议
- 链路层进行交换机级别的转发,可能会用到链路层协议,广播或者PPP协议
14年真题本质上是在考这个,SMTP是应用层协议,如果一开始就不调用,那么后续就不可能用到了
15年真题考了HTTP报文,注意connection字段,close标识非持久链接。
22年真题考了HTTP传输过程,1.1协议下,问至少
,就要用流水线传输,默认慢启动,因此传输过程为TCP建立(1RTT)+html(1RTT)+图像(2RTT)=40ms,选B
拓展一下,在流水线+1.1协议的前提下,窗口是会不断增长的,如果一个文件的大小小于一个窗口,那么一轮发送多少文件呢?答案是一个,即使窗口大于文件大小,一次最多也只能发送一个对象,不然无法区分,也就是说如果考的难一点,就会出现一个现象:刚开始文件越发越快,后面文件发送速度就饱和了,一个RTT一个对象。
区分两个服务器
本地域名服务器和代理服务器的区别,代理服务器是针对URL资源的,比如你的b站视频,网页,而本地域名服务器是针对<域名,IP>的键值对的。
电子邮件
电子邮件的发送是异步的:总的来说就是两次SMTP,一次POP3。涉及到非ASCII的还需要MIME协议辅助转化。
传统的邮件需要用户代理,说白了就是客户端,客户端里封装了SMTP协议和POP3协议,而万维网电子邮件把两端变成了浏览器的HTTP协议,只有中间还是SMTP协议。
这样的好处在于不用客户端了
动态主机配置协议——DHCP
DHCP协议支持主机即插即用地接入局域网中,一旦接入,自动配置IP相关的信息。
省流版本:
- 广播发现
- n台服务器提供
- 选择,广播这个选择信息。
- 被选择的服务器单播ACK
之后就是维护了:
- 重新登陆
- 更新租约
简单网络管理协议——SNMP
管理员是客户机,被管理的机器是服务机。
应用进程跨越网络的通信
P2P应用
本质还是CS,只是每个主机都可以作为C。
![Logo](https://devpress.csdnimg.cn/79de2bf0b7994defa4242ef90d5513fa.jpg)
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)