计算机网络速描
计算机网络
计算机网络分层?
- OSI 7 层: 应用层,表示层,会话层,运输层,网络层,数据链路层,物理层.
- 常用的 5 层: 应用层(涵盖osi 应用层/表示层/会话层),运输层wu,网络层,数据链路层,物理层.
- 应用层: HTTP DNS等,报文.
- 运输层: TCP(报文段) UDP(用户数据段)
- 网络层: 分组
- 数据链路层: 帧
- 物理层: 比特(01 电信号)
- 从数据来看整个网络的分层,是自顶向下一层一层的往数据包上添加头尾,到中间或者目的地再一层一层的拆,直到得到最后的数据.
- TCP/IP 实际上是 4 层.5层模型的数据链路层\物理层合并成网络接口层.但并不是严格的分成,应用层可以使用网络层(IP层).
什么是互联网?
- 互联网大概可以说是各个网络之间互联互通形成的最大的计算机网络.
- 一般企业和个人是接入 ISP(互联网服务提供商) 来接入互联网.
- ISP 也有分层,第一层 ISP ,区域 ISP,接入 ISP.各个 ISP 直接互联互通,形成了现有的互联网.其实有些互联网公司像 Google 等都建设了自己的通信网络.通过 IXP 与区域 ISP 相连提供服务.
电话网的电路交换和分组交换?
- 电路交换是在两点直接建立物理链路.传输性能好,但对整个电话网的利用率过低.
- 分组交换,在同一线路上传输多组信号.比如将声音调制,然后通过约定的协议一次性传输多组信息,到了目的站再拆分到各自的终点.缺点是不如电路交换的可靠性.分组交换是尽最大可能到达,并不保证 100%.
互联网通信的时延有那些?怎么计算?
- 排队时延,分组在路由器输入/输出队列的等待时间.与网络通信量有关.
- 处理时延,主机路由器收到分组处理的时间,包括拆包,校验等等,路由还有路由选择.
- 传输时延,主机路由器传输数据帧的时间.delay = l(bit) / v(bit/s)
- 传播时延,电磁波在介质中传播花费的时间.例如光速决定了中美最佳的 rtt 时间不会小于 133ms.
应用层
简述一下 DNS .
- DNS 是个分布式数据库,提供域名到 IP 地址的转换.
- 有 3 个层级,根域名(.),顶级域名(com),二级域名(google.com).
- dns 通常使用 udp 传输,端口 53.只有当传输的子节大于 512 时,才会使用 tcp.
- 近年来还出现了 dns over tls 和 dns over https.
FTP
- ftp 是个文件传输协议.
- 通常使用 21 端口,tcp 传输
- 分为主动模式和被动模式(通常使用).
- 主动模式下,服务器请求客户端,服务器端口 20,客户端不定.
- 被动模式下,客户端建立数据连接,端口号由客户端自行决定.
DHCP
- 没错 DHCP 是个应用层协议.虽然它干的活与应用层没啥关系.
- DHCP 可以完成的内容包括,分配客户端 ip 子网掩码 和 网关ip.
- 过程:
- 客户端入网,发送 Discover 报文,目的地ip: 255.255.255.255:67 源ip:0.0.0.0:68,UDP 协议.
- DHCP 服务端收到 Discover 报文,将分配的ip地址等信息通过 Offer 报文回复给客户端.
- 客户端可以接收多个 DHCP 服务器的 Offer,但只能选择一个,选择后回复 Request 报文给对应服务端.
- 同样对应的 DHCP 服务器收到 Request 报文后,回复 ACK 报文,完成分配的过程.其他 DHCP 服务器,收到不是自己的 ACK 后,可以将向前分配的 ip 信息释放等.
Telnet
- 远程登陆协议,运行在 tcp 上.
- 早期互联网常用,但 Telnet 是明文协议,现在通常被 SSH 代替.
电子邮件
- SMTP: 发送协议,基础版本只能发送 ASCII,后来的 MIME 拓展可以发送二进制文件.使用 SSL 加密版本称为 STMPS.
- POP3: 拉取协议,POP3 以前拉取邮件后,服务器会删除副本,POP3 则一般不会.使用 SSL 的加密版本称为 POP3S.
- IMAP: 拉取协议,客户端与服务端保持同步.与 POP 不同,不会主动删除服务器邮件副本.使用 SSL 加密版本 IMAPS.
Web 页面请求过程(从 0 开始)
主机浏览器起了一个 tcp 的 socket,向服务器发送 http 请求.但启动 socket 还需要服务器 ip ,此时开始 DNS 查询,发送 DNS 查询报文,但是这里主机只知道 DNS 服务器的 ip,但是不知道 MAC 地址,链路层无法通信,所以还需要先通过 ARP 请求 DNS 服务器的 MAC 地址.但开始时候主机时候主机连 ip 地址都没有,需要通过 DHCP 请求分配 ip 地址.
DHCP 请求 ip 地址.
- DHCP 请求报文,发送到 255.255.255.255:67 ,自身是 0.0.0.0:68. 对应链路层的帧目的地址 FF:FF:FF:FF,广播到网络所有设备上.
- DHCP 服务器收到广播帧,回复主机需要的 ip 地址,dns,默认网关,子网掩码.udp 67.
- 主机收到配置信息后,配置相关信息,最后回复 DHCP 服务器 ACK,完成 DHCP 过程.
ARP 请求 DNS 服务器 MAC 地址.
- 主机向网关发送一个 ARP 查询报文,包含网关的 ip 地址,广播目的地为 FF:FF:FF:FF.
- 网关响应这个请求,在 ARP 广播表找到对应的 MAC 地址,再返回一个 ARP 应答报文.
- 主机收到应答,解包得到网关的 MAC 地址,存到 ARP 广播表里,这样 DNS 的报文就能在链路层传输了.
DNS 查询
- 主机向网关发送 DNS 查询,UDP/53.
- 链路层上,网关收到对应的帧,拆包,如果 DNS 有缓存,直接返回(UDP/53).没有缓存,通过路由表向上一级递归查询.
- 直到最后主句收到 dns 的应答,得到服务器 ip 地址.
HTTP 请求
- 启动 tcp socket,HTTP GET.
- 运输层需要 tcp 3次握手,建立连接.默认 80 端口.
- 服务器收到 HTTP Get,返回 web 内容.
- 主机收到内容,浏览器渲染显示.
传输层
什么是传输层?
- 传输层为进程提供逻辑信道连接.屏蔽来自网络层的细节.
- 我们熟悉的 TCP/UDP 都是传输层协议.
UDP/TCP 特点/异同?
- udp 即用户数据包协议,无连接,一对一,一对多,多对多.
- 应用层下来的报文,添加上udp报头,就传向了网络层.不提供差错校验,拥塞控制等.
- tcp 即传输控制协议,面向连接,一对一的可靠全双工通信.提供差错校验,拥塞控制等.
- udp 即用户数据包协议,无连接,一对一,一对多,多对多.
udp / tcp 报头.
- udp: 伪头部x12 源端口x2 目的端口x2 长度x2 校验和x2
- 伪头部: 运行在 ipv4 需要计算校验和,需要添加一个伪头部.包括一些 ipv4 信息.
- tcp: 源端口x2 目的端口x2 序号x4 确认号x4 数据偏移+保留x1 各类标志位x1 窗口x2 校验和x2 紧急指针x2
- 序号: 字节流编号,(SYN=0)
- 确认号: 期望收到的数据序列号.已经收到的数据字节长度+1.
- 数据偏移: 数据部分距离报文段起始部分的偏移量,实际上是首部的长度.
- ACK: 确认字段,=1 为有效.
- SYN: 同步序号,=1 为有效.
- FIN: 终止标志位,=1 表示数据发送完毕.释放连接.
- 窗口: 拥塞控制使用.
- udp: 伪头部x12 源端口x2 目的端口x2 长度x2 校验和x2
tcp 的 3 次握手?
- 3 次握手是为了建立可靠的 tcp 连接.
- A -> B,SYN = 1,ACK = 0,随机选择初始序号 X.
- B -> A,SYN = 1,ACK = 1,确认号 X+1,随机选择初始序号 Y.
- A -> B,SYN = 1,ACK = 1,确认号 Y+1,序号 X+1.
- B 收到确认,建立连接完毕.
为什么 tcp 需要 3 次握手?
- 最主要的为了避免服务端浪费资源等待无效的 tcp 连接.
- 理想情况下,2 次握手就能建立一个连接,A->B B->A.但是现实的网络层提供的是尽可能送达,不是一定送达.两次握手,server 端,每次收到一个请求就要分配一点资源给可能建立的 tcp 连接,如果是 2 次握手,client 到 server 不畅通,server 可能一次性收到大量 client 的请求,但是此时 clent 已经认为这些连接已经失效了,不会回复 server 的请求,不会建立 tcp 连接.但此时 server 已经分配了大量资源给可能的 tcp 连接,造成浪费. 3 次握手就没有这样的情况.
tcp 4 次挥手?
- 4 次挥手是为了稳定关闭 tcp 连接.
- A->B,FIN = 1.序号 X.
- A 我没有数据要发了.进入 FIN_WAIT_1.
- B->A,确认号 X+1.
- B 我知道你没有数据要发了.
- A 收到,进入 FIN_WAIT_2.
- B->A,FIN = 1.
- B 我也没有数据要发了.进入 LAST_ACK.
- A->B,ACK .
- B 收到,我知道你没有数据要发了,B 关闭连接.
- A 进入 TIME_WAIT,等待 2MSL 没收到 B 的信息,就关闭连接.
为什么断开 tcp 连接,要 4 次挥手? 为什么 A 关闭连接还需要等待 2MSL?
- 主要是因为 tcp 全双工的特性.tcp 两个方向都能传,就需要把两个方向都关闭才算是断开了 tcp 连接.
- A 等待而不是直接关闭连接.
- ip 层并不能确保 A 最后的 ACK 绝对能送到,如果丢了,B 可能还会重新发送报文请求 A 释放连接.
- 等待此次连接的报文在网络中完全消失,防止下次新连接建立时还有旧连接的报文传过来.(到底也只是个预防)
tcp 怎么保证传输的可靠性?
- 因为网络层是尽最大可能交付,无法保证数据一定送到,因此 tcp 的可靠传输是通过一系列重传实现的.
- tcp 建立连接时,接收和发送的双方都确认了各自的序号(X Y),每个包都会在 tcp 传输中确认.
- tcp 的发送和接收方都有一个窗口,发送窗口内都允许发送,接收窗口内的都允许接收,接收窗口内允许乱序达到.发送/接收窗口满,向上层交付数据.窗口滑动(就是 tcp 头部的序号)
- 重复累计确认: 当发送方收到多次对同一包的确认时,发送方认为这是链路丢包的信号,就重传最后一个未被确认的包.(重复次数一般为 3 次)
- 超时重传: 发送方有一个保守估计包到达的计时器,过了计时器还未收到确认,就重传这个数据包.每次重传都重置计时器.
tcp 拥塞控制?
所谓拥塞控制,就是控制数据发送的速度,避免网络堵塞.可以将网络类比成高速公路,汽车是数据包,必须合理规划汽车流量高速公路才能正常运行,传输数据,如果不进行流量控制,高速一样寸步难行.
一些概念
- cwnd: 拥塞窗口的变量.cwnd 决定了发送方可以发送最大速率.(单位是报文段)
- 发送窗口: 一般等于 cwnd,但是考虑接收方的接收窗口,有可能小于 cwnd.
- ssthresh: 慢开始门限,开始时候 cwnd 是指数级增长,但真实的网络速率始终是有限的,当 cwnd > ssthresh 时,cwnd 开始线性增长,一次只 +1.
慢启动
- 开始时 cwnd 只设置为 1,经过一个 RTT 时间(报文往返一次),cwnd *= 2.直到 cwnd >= ssthresh.
- 慢开始的图形,就是一个指数函数.慢只是初始值小,
拥塞避免(加法增大,也说线性增长)
- cwnd > ssthresh 时,cwnd += 1.慢开始的增长曲线实在恐怖,超过限值,开始线性增长,避免一下碰到网络堵塞.
乘法减小
- 当遇到丢包时,加法增大结束,将 ssthresh = cwnd/2 .之后 cwnd = 1,进入慢恢复过程(慢恢复与慢开始相同).
- 效果是遇到丢包时,相当于直接把速率掐了,大大减少了注入网络的数据包.
一个典型的调度过程
- AIMD
但是有两个问题
- 一旦进入拥塞,速度几乎一下掐掉.但有时只是网络波动或者邻居出了点问题. -> 快重传/快恢复
- 对丢包的容忍太低了,在广域网丢包非常常见,导致最终的 cwnd 只能收敛于一个非常小的值. -> BBR
快速重传/快恢复
- 快重传: 在可靠传输一节,提到了发送方对每个发出的数据包有一个重传的计时器,计时器到时间就重传这个报文.快重传是不理会这个定时器,但发送方连续收到 3 个重复确认时,直接重传下一个报文,不再等待定时器.原理是既然能收到确认,那么网络并没有堵塞,只是发送的报文丢失了,那么重传下一个报文即可,不再需要等待定时器.
- 快恢复: 快重传时,此时相当于发送了拥塞,要控制发送的速率了.但单单快重传发生时,此时并不认为网络发生了严重堵塞.此时要执行的是快恢复.快恢复,ssthresh = cwnd/2,但是 cwnd = ssthresh,直接进入拥塞控制的线性增长.不再经过慢恢复 cwnd = 1 的过程.
- 快恢复避免了慢恢复的失速过程.因此在当前应用中,慢开始(恢复)只在 tcp 建立和 tcp 重连时出现.其他情况下都是快恢复.
BBR
BRR 是 google 开发的 tcp 拥塞控制算法,在 linux 4.9 进入内核.
BBR 致力于解决两个问题
- tcp 对丢包的严格要求.有丢包的线路 tcp 速度非常惨淡.
- 降低链路上缓存的占用.在慢开始阶段,tcp 会一直把链路灌满了才开始降低发送速度,这个过程中链路路由器的缓存都占满了,延迟也大了,出现拥塞丢包.之后发送速度才会下来,还是断崖式的下架.但线路上有大量tcp流量时,非常容易出现路由缓存占满,延迟超大.BBR 希望能避降低缓存占用,降低延迟.
解决
- 其实拥塞丢包并太影ce响数据的传输,错误丢包才是最影响数据传输的,但是发送端并不能区分拥塞丢包和错误丢包.既然不能区分,BBR 干脆不考虑丢包了.
- 既然不再把丢包作为网络拥塞的标志,那么就没有必要把网络占满来估计窗口大小了.BBR 测量带宽和延迟代替这个过程.窗口 = 带宽x延迟
但是带宽和延迟并不能同时测到,测试带宽需要把链路占满,此时延迟变大.测量延迟,要求带宽不能太大,此时测不到正确的带宽.BBR 干脆交替测量这两个值,把一段时间内带宽极大值和延迟极小值作为带宽/延迟的估计值.
启动: BBR 开始阶段类似 tcp 的慢启动,指数增加 cwnd.慢启动时链路的缓存几乎没有占用,将此时的延迟极小值作为延迟的估计值.但是之后 BBR 不再以丢包作为拥塞的标志.BBR 根据收到确认包的数量,但有效带宽不再增加时,才进入拥塞控制.实际上进入拥塞时已经是 带宽x3 × 延迟,后面会把 带宽x2 X 延迟释放掉.
排空: 指数级别降低发送速率.释放掉占用的 带宽x2 X 延迟.直到往返的延迟不再降低.
之后 BBR 进入探测阶段,交替探测带宽和延迟,具体就是定期参数增加发包速度,如果收到确认的速度也增加了,就进一步增加发包速度.但是延迟变动怎么办? BBR 会每过 10s 发现延迟没有变化时(即没有更低的延迟时)进入延迟探测阶段,在 200ms 内只发送 4 个包,得到最小的延迟值作为延迟的估计.
网络层/链路层
协议众多,互相交织,还是换一种风格…
互联网的本质是互联,最简单的大概是几台电脑插上网线一连就完事.那么问题来了,电脑直接怎么区分谁是谁呢?
起到这个作用的网卡的 mac 地址,mac 地址 48 位,6 个子节,每个网卡都不一样.有了地址还不行,还得有个交流的协议吧?总不能你说英语我说土著方言吧.这个协议目前在局域网最多的是以太网协议.
以太网协议有个特点是,网内每个电脑都有个大喇叭,传输数据就喊一声那个谁谁谁(广播)..,其他人都能听到,但是只有被喊道的人才回答.闲的时候还好,忙起来谁都听不见,这里就需要处理这种嘈杂,但是这是另一个话题了.
以太网有个问题,只能适用于同一个广场组网,相聚很远的地方就没办法用了,而且受制于以太网的通信方式,太远的地方效率太低.你能想象纽约时代广场喊话北京天安门,就为了问苹果几毛钱一斤?且不说为了能传到提升功率要覆盖全地球,就是问个价钱让地球人都知道,这一点就不安全.因此在广域网上还需要另外一套协议,这里实际上指的是 ip 协议,常见是ipv4 还有近些年逐渐普及的 ipv6.下文还是 ipv4 为例.
ip 协议的规则很简单,就是给互联网中的每个主机分配一个网络地址,大家按照网络地址互相投递邮件.
先从小的来说,互联网是由众多局域网互联组成的,广域网用的是 ip 协议,局域网用的是以太网,怎么把 ip 协议和以太网统一起来?用到了软件工程最好用的做法–分层.为了统一,我们局域网也用 ip 协议,但是我们把 ip 协议定义在以太网的上一层.具体来说以太网属于互联网分层的链路层,ip 协议是网络层(也称 ip 层).这样 ip 协议统一了,以太网也不需要改动.
ipv4 的地址是 32 个二进制数字,习惯上我们将其分为 4 段,一个典型的 v4 地址:
127.0.0.1
.地址前部分标识网络,后部分标识子网(局域网),但问题就在这个分界点怎么界定?不同规模的局域网需要的分界点也不一样.这里就需要子网掩码,例:如果子网的长度是 8 ,正好是最后一个十进制标识.那其对应的子网掩码是11111111.11111111.11111111.00000000
十进制255.225.225.0
.192.168.3.66
和192.168.3.254
要怎么判断它们是不是一个子网呢?与 子网掩码255.225.255.0
分别做 AND 运算,结果相同就是同一子网.但是子网掩码有时还是麻烦,就有更加简化的无类别域间路由(CIDR).例子中那段子网就可以表示成:192.168.3.0/8
.好,局域网适配 ip 协议改动完了,那还有个问题,局域网通信在链路层(以太网)靠 mac 地址区分计算机.而在网络层(ip 协议)是依靠 ip 地址区分.通常在分层中上层依靠下层实现.那就意味着在局域网中,网络层的 ip 地址应该与链路层的 mac 地址存在关联,这样整个局域网模型才能正常工作.事实也确实如此,起到这个关联的就是 ARP 协议.
想象一个局域网的传输场景,网络层已经知道了目的地的 ip 地址,但是链路层要进行通信,还需要目的地 ip 对应的 mac 地址,这就需要 arp 协议了,主机会向网关发起 arp 请求,包含网关的 ip 地址,广播目的地为 FF:FF:FF:FF,网关会维护一个 ip 地址和 mac 地址的关系表,返回 arp 应答.主机收到了目的地的 mac 地址,正常通信就行了.
来看一下局域网->广域网的过程.一般而言一个局域网里都有一个与广域网连接的入口,称为网关.局域网所有与广域网有关的请求都在网关进出.网关一般有两个 ip 地址,一个广域网的 ip 一个是局域网的 ip ,当局域网的请求发出去比较简单,但是要怎么接收广域网的回复呢?广域网看不到网关背后局域网的成员,这时涉及了 NAT(网址转换协议)
在实际传输中,向外的请求到达网关时,网关会进行源地址转换,将向外请求的 源ip地址替换成网关的广域网ip,使得这些请求可以进入广域网.同时网关会记录并维护一个 NAT 表,标识 内网ip:端口 —外网ip:端口.当收到广域网的回复时,网关又会把这些向内请求的目的地 ip 替换成局域网内的 ip,这样这些请求就能进入局域网内部了.
聊完了局域网,来看一下广域网,首先如果要构建广域网,我们不可能直接将所有不同规模的局域网对等相连.受限于地理和国家因素,首先是较小规模的局域网相连,然后是较大的局域网相连,最后才算这些实体之间互联互通,形成广域网.从上到下一点一点看.
讨论到此需要涉及一个新的概念 AS(自治系统),AS: 维基的定义是一个或多个实体管理下所有 ip 和路由器的组合.在 AS 内执行共同的路由策略.每一个 AS 都有一个唯一编号 ASN,这个编号是在申请建立 AS 时候就确立的,申请 AS 时会分派到对应的 ip地址,不会重复.可以将 AS 理解成广域网上一个大的围城,围城内部执行相同的规则(路由),外界现要访问围城内部,必须经过围城这个边界.
互联网发展早期是一个运行商对应一个 AS,之后随着规模剧增,遍不再有对应的关系,一个 ISP 可能拥有多个 AS,同时不止 ISP 大型的互联网公司为了更快的访问速度也申请了 N 多的 AS 以服务不同地区的客户.广域网就建立在这些 AS 互联互通的基础上.
理想情况下各个 AS 应该对流量一视同仁,拥塞调度路由选择等都交给统一的算法,就像 AS 不存在一样.但是现实并不是美好的,运营商有盈利压力,不同地区网络设施建设费用也千差万别.统一的调度根本是奢望,这也是 AS 存在的意义,AS 之间互联互通遵循 BGP (边界网关协议),AS 可以定义互联的规则,例如可以不让其他 AS 的流量通过等.要注意 BGP 协议仅仅是寻找到比较好的路由而不是最佳的路由.每个 AS 都必须配置 BGP,BGP 使用 tcp 进行通信.
说完了 AS 之间,我们来看看 AS 内部,我们可以把 AS 内部近似看作是平等的,没有流量的歧视.AS 内部最大的问题就是如果在组成 AS 的众多路由中,迅速找到一条最快到目的地的路.AS 内部的路由选择有 RIP(路由信息协议) 和 OSPF(开放式最短路径优先),现在一般都是 OSPF.OSPF 的基本原理是图论中的 Dijkstra 算法.
物理层
全/半/单工通信.
带宽调制…略…