最近对计算机网络相关的知识进行了复习,包括对之前不太熟悉的部分重新学习了一次,做了一些总结。移除了大部分偏向物理层的知识,主要是 TCP/UDP 协议和基于 TCP/UDP 实现的应用层协议相关的知识。主要是基于移动端开发者的角度来概括需要知道的计算机网络知识体系。 如果想建立完善的计算机网络相关的知识体系,最好是认真学习一次,这篇文章只能作为一个知识图谱进行学习或者复习。
物理层
物理层处于网络中的最底层,它定义了将数据转为电子信号在通信媒介(比如光纤,电话线)中进行传输的方法。
物理层主要是将上层的以太网帧转换成电子信号或者光信号在通信媒介中进行传输,接收时将电子信号转为以太网帧。
链路层
定义了一系列在物理设备之间数据传输的标准,比如以太网和 WiFi 标准。物理设备主要交换机这类硬件。
MAC 地址
每一个网卡有一个唯一的 MAC 地址代表这个网络设备。
以太网帧
链路层将数据分割为多个帧在物理设备间进行传输。一个帧由头部,数据段和帧校验序列组成。
帧头部
-
类型
表示数据类型,比如 IP4, IP6,ARP。
-
帧长度
一个帧的长度等于头部+数据段+帧校验序列的长度,头部和帧校验序列的长度是固定的。一般以太网的最大帧长度为1518字节。
为什么要限制以太网帧的长度?
- 帧太长传输的时间也比较长,如果帧校验出错重传也是很大的消耗。
- 虽然现在有些新的网络设备支持巨型帧,可以携带更多的数据。但是需要两台通信主机之间所有网络设备的支持。
因为头部的固定字节开销,传输大量数据时,帧长度越大会更加效率。
-
源地址 SRC
用于识别发送端的设备。
-
目的地址 DST
用于识别接收端的设备。
帧数据
用于存放一个帧的数据,例如存放上层 IP 数据包。
帧校验序列
主要用于接收端收到数据帧后对数据帧校验。如果帧在传输过程中受损,通常被丢弃。
MTU
最大传输单元,代表每个帧数据段可携带的最大字节数,通常为1500。
当 IP 层发送比 MTU 更大的数据包时,需要在 IP 层进行分片处理。
失序
因为每一个以太网帧可能经由不同的网络传输路径进行传输,所以并不能保证接收的顺序和发送顺序一致。
链路层主要是负责 IP 包与以太网帧之间的转换。
网络层
IP 仅提供分片重组数据包的功能,并不能保证数据到达和多个包接收的顺序与发送顺序一致。
IP
IPv4
IPv4 头部
版本
表示数据包的版本号:IPv4 或者 IPV6。
总长度
表示IP 数据包的长度
标识
标识用于区分同一个数据包的不同分片用于重组。
分片偏移
分片偏移标识每一个分片的字节偏移用于重组。
协议
表示数据包的类型,比如 TCP 或者 UDP。
头部校验和
接收端用于校验数据包头部传输过程中是否出错,如果头部出错会丢弃数据包。
源 IP 地址
发送端 IP地址
目的 IP 地址
接收端 IP 地址
数据
保存上层 TCP/ UDP 数据包。
分片重组
分片
由于链路层对可传输的每个帧的最大长度有上限,所以 IP 会比较 MTU 和数据包的大小,当数据包大于 MTU 则进行分片。分片后每个数据包独立发送,互不影响。
重组
因为每个分片独立发送,同一数据包的不同分片可能经由不同的路径到达接收端。当一个 IP 数据包发送时被分片后,在接收端需要将多个分片的数据包进行重组合并。当任何一个分片丢失,IP 层会丢弃整个数据包。
重组超时
当接收到第一个分片时,会开启一个定时器。当超过定时器时间一个数据包还有分片没有到达,将丢弃这个数据包。
IPv6
- 可以使用更多的 IP 地址。
- IPv6 简化了头部,可以减少头部数据量。
- MSS 默认为1440字节,相比 IPV4更长。
- 去掉了头部校验和,增加传输效率。
DNS
域名系统主要是为了方便记忆。DNS 负责将域名转换为主机 IP 地址, 因为 IP 层只能识别 IP地址。
ARP (地址解析协议)
在以太网中传输时,主机与主机之间通过 MAC 地址来通信。但是在网络 IP 层,主机与主机之间通过 IP 地址来通信。 ARP 就是主机在发送以太网帧前将目标 IP 地址转换成目标 MAC 地址的过程。
NAT
DHCP
传输层
端口
主要用于区分发送和接受的进程应用。
丢包
- 在有线网络中,路由器或交换器中发生拥塞是主要原因。
- 在无线网络中,传输和接收错误是主要原因。
- 包括 IP,链路层,UDP/TCP 层校验和失败。
UDP
UDP 一种基于数据包的传输层协议。它不需要建立连接,只提供最基础的数据包传输功能。不能保证数据一定被接收,也不保证数据包接收的顺序和发送端一致。
UDP 包
头部
源端口号
发送端端口号
目的端口号
接收端端口号
长度
包长度,通常 UDP 应用程序将包长度限制为 512 字节以内,因为 IPv4 最小 MTU 为 566字节。
校验和
用于校验 UDP 数据包在传输过程中有没有损坏,如果检测出错会直接丢弃数据包。
数据
TCP
TCP 是一种基于二进制流的传输层协议,提供一系列机制保证连接的可靠性。
- 通过重传机制来保证发送数据的接收。
- 通过滑动窗口和拥塞控制来改变传输中的发送速率避免网络阻塞。
因为 TCP 是基于二进制流的协议,没有消息边界的概念。也就是说接收端不能保证每次返回给应用程序的数据等于发送端一个包的大小,也可能一次返回多个包数据。所以一般应用端会增加额外的头部信息来判定一个包的大小进行拆分。
TCP 头部
源端口
发送端端口号
目的端口
接收端端口号
序列号
序列号表示该报文段的第一个字节在数据流中的字节偏移。
确认号
表示该确认号的发送方期待接受的下一个序列号。
ACK
表示这是一个 ACK 包,用于发送端确认消息已被接收。
SYN
表示这是一个 SYN 包,用于建立连接。
FIN
表示这是一个 FIN 包,用于关闭连接。
窗口大小
用于流量控制动态调整窗口大小。
TCP校验和
接收端用于校验 TCP 包在传输中有没有发生错误,如果发生错误 TCP 会丢弃该包,不会返回 ACK 确认。
TCP 选项
MSS
最大段大小指接收方可以处理的最大包长度,发送方不能大于该长度。默认值为536(IP层为576,减去 TCP 头部)。
SACK
用于重传机制中,表示丢失的多个包序列。
建立连接
- 客户端发送一个 SYN 报文和初始序列号 ISN。
- 服务端返回一个 SYN 和初始序列号 ISN。并且将客户端的初始序列号加1作为 ACK 返回。
- 客户端将服务端的初始序列号加1作为 ACK 返回。
3次握手主要是为了保证一些信息的正确交换,比如 TCP 选项,初始序列号等。
窗口机制
- 基于窗口机制可以同时传输多个包增加传输效率和网络的利用率。
- 因为 TCP 需要保证数据接收的顺序,当发生丢包或者接收到失序包时,需要等待前面的包都接收到或者重传以后,再返回给应用程序。
重传机制
重传用于在丢包时将数据包重新发送,这也是 TCP 可以保证数据传输可靠的原因。
RTT
表示发送端发送一个包到接收到 ACK 的时间。
RTO
超时重传时间,一般根据 RTT 和 TCP 时间戳选项 进行动态计算。
超时器重传
发送方等待一段时间(RTO)以后, 没有收到 ACK 确认, 会触发超时重传。
快速重传
当接收端收到失序的数据包(也有可能是丢包)时,会立即重传 ACK 包括 SACK 的信息。发送端接收到 ACK 消息以后,等待几个 ACK(可能之后收到丢失的ACK)来决定是否重传数据。这样可以确保比超时器重传更快速的重传丢包。
重传机制
- 发送方发送一个分组, 等待一个 ACK。
- 接收方收到分组, 发送对应的 ACK。
- 发送方收到 ACK, 发送成功。
流量控制
- 通过动态调节窗口大小来控制发送端的传输速率,确保接收端不会溢出。
- 通过接收方返回ACK里携带的窗口值动态调整发送方窗口大小.
延迟 ACK
- 允许 TCP 延迟一段时间发送 ACK, 以便将 ACK 与同方向需要传的数据一起发送.
- 延迟发送有一个最大值,当超过最大值以后如果没有发送 ACK , 则不再等待, 立即发送.
- 减少了 ACK 传输数量, 可以一定程度减轻网络负载.
Nagle
- 当一个 TCP 连接中有正在传送中的数据(已发送还未被确认的数据), 小的报文段会被收集起来, 等在传数据收到 ACK 以后, 将小数据整合到一起发送.
- 主要是为了减少小数据包的数量, 因为小数据包头部占用数据比例更高. 延迟低的场景不适合使用.
滑动窗口
发送端
- 发送端只能发送窗口范围以内的包, 包括(已发送未确认)还有(即将发送)的包.
- 发送端根据接收端返回的 ACK 和窗口信息动态调整窗口大小. 窗口大小 = 已发送未确认 + 即将发送.
- 当发送的数据收到ACK确认后, 窗口左侧右移. 接收端返回窗口变大时, 窗口右侧右移.
接收端
- 接收端只能处理接受窗口范围内的序列号包, 窗口左边的属于重复数据(已接收并确认), 窗口右边超出范围, 都会直接丢弃.
- 到达数据序列号等于左边界序列号时, 左边界右移.
窗口探测
- 零窗口的时候发送端会开启计时器间歇性的查询服务端, 要求返回最新的窗口数.
拥塞控制
路由器因无法处理高速率到达的流量而被迫丢弃数据信息的现象称为拥塞. 为了防止网络因大规模的通信负载而瘫痪, 当可能出现拥塞情况时, 减缓 TCP 传输的速率.
慢启动
- 主要是为了防止短时间内大量数据注入导致拥塞.
- TCP 在建立新连接时执行慢启动, 直到有丢包时, 执行拥塞避免算法进入稳定状态. 当检测到丢包时, 也会执行慢启动算法.
- 比如开始发一个包, 当收到 ACK 时发送两个包, 以此递增一直到丢包为止.
拥塞避免
根据可以发送的窗口值和丢包时的窗口值, 动态计算最大的接收端可以接受的窗口值.
TCP 保活
因为 TCP 连接状态基于状态机维护,当处于连接状态的时候只要双方不主动断开连接,连接会一直保持,即使路由器出现故障,网线断开连接。所以当 TCP 连接空闲没有数据传输的时候,需要检测当前连接的可靠性,客户端服务端都需要了解对方的当前状态。
- 运营商的影响,当一个长连接处于空闲时间比较长的时候中间链路会中断。
- 客户端网络状态改变或者网络断开,服务端需要根据用户的离线状态进行处理同时可以移除无效的 TCP 连接减轻负载,客户端也可以重新建立连接。
- 一般通过应用层发送空的心跳包实现,不过发送的间隔时间,判定连接断开的次数需要仔细确认,尽量减少对网络的消耗。虽然 TCP 也有 KeepAlive的功能,但是时间间隔至少为2小时,所以很少使用。
应用层
HTTP 1.1
HTTP 请求响应过程
- 客户端发起与服务端建立一个 TCP 连接。
- 客户端发送 HTTP 请求,包括 HTTP 头部信息的发送。
- 服务端处理请求并返回响应,之后关闭 TCP 连接。
请求
Method
GET
参数直接放在 URL 链接里,适合传输少量数据。
POST
参数放在请求 body 里,可以传输大量数据比较安全。
头部
缓存
Cache-Control
public, max-age=0
public代表可以缓存。
max-age代表缓存时间,在有效期内不会请求服务器
ETag
用标识符来做对比处理,如果一样可以使用本地缓存。
Last-Modified
用时间来做对比处理,如果一样可以使用本地缓存。
Range
客户端只获取一部分 HTTP 消息数据,比如实现文件下载的断点续传功能。
压缩
对于某些文件在传输之前进行压缩处理,可以大幅减少网络中需要传输的数据。客户端服务端协商出压缩算法,然后双方进行压缩解压缩处理。常用的压缩算法:gzip,br。
Keep-Alive
HTTP/1.1 新特性,保持一个 TCP 的持久连接,所有的 HTTP 请求都使用同一个 TCP 连接,避免多次创建 TCP 连接的消耗。HTTP/2 忽略该特性。
Pipeline
HTTP/1.1 新特性,可以将多个 HTTP 请求放到一个 TCP 连接中发送,而在发送过程中不需要等待服务器对前一个请求的响应。不过必须一个响应完全返回后,下一个响应才会开始传输。已经被 HTTP/2 multiplexing 特性取代。
响应
状态码
200+:请求成功
300+:重定向
400+:客户端错误
500+:服务端错误
HTTP status response codes
HTTP
HTTP/2
特性
二进制格式
HTTP/1 采用文本格式进行数据传输, HTTP/2 采用新的二进制分帧机制。一条 HTTP 消息由多个帧组成,每个帧都包含头部,头部包含数据流标识符可以识别出当前帧所属的数据流。
二进制分帧机制是实现多路复用和数据流优先级的基础。
多路复用
一个 HTTP 连接代表一个数据流。多个 HTTP 连接可以共用一个 TCP 连接,并且多个 HTTP 数据流可以并行交错的发送,互不干扰。接收端根据每个帧头部识别出所属的数据流组装数据。
因为基于 TCP 实现,还是有 TCP 窗口队头阻塞的缺点。
数据流优先级
可以配置一个数据流的优先级,优先级更高的流可以获得更高比例的网络资源。
头部压缩
优化了头部压缩算法并且减少了需要传输的头部数据量。
服务端推送
服务端可以主动将数据推送到客户端。
HTTP/2 简介
HTTPS
HTTPS 增加了 TLS 协议来保证传输过程中的数据安全,建立连接时会增加 TLS 握手的过程。
TLS
TLS 1.2
连接建立
- 客户端发送一个握手,包含一个随机数和客户端支持的加密协议。
- 服务端返回证书,生成一个新的随机数。
- 证书中的公钥经过权威机构私钥加密,使用本地权威证书中的公钥对证书公钥进行解密。
- 客户端校验证书,根据之前的随机数生成一个新的随机数秘钥,然后将秘钥使用证书中的公钥加密之后发送到服务端。
- 服务端确认消息,使用私钥对秘钥进行解密,之后双方根据三个随机数生成秘钥,秘钥对数据进行非对称加密进行数据传输。
TLS 1.3
TLS 1.3 是最新的 TLS 标准, 相比 TLS 1.2 有很大的提升。
减少握手时间
TLS 1.2 需要两次往返(2-RTT)完成握手,主要是因为 RSA 密钥交换。TLS 1.3 优化了密钥交换,只需要一次往返(1-RTT)完成握手,并且支持零RTT(0-RTT)模式。
安全性增强
- 精简加密算法,删除了那些不安全的对称加密算法。
- 优化密钥交换,移除了 RSA 密钥交换。RSA 有一个缺点:如果有人记录加密的数据,然后获得服务器的RSA私钥,他们就可以解密数据。
现在仅支持以下加密算法:
TLS13-AES128-GCM-SHA256
TLS13-AES256-GCM-SHA384
TLS13-CHACHA20-POLY1305-SHA256
TLS13-AES128-CCM-SHA256
TLS13-AES128-CCM-8-SHA256
TLS 1.3科普——新特性与协议实现
Cloutflare:TLS 1.3解读 你想了解的都在这儿
QUIC
QUIC 是一种新的传输方式,与TCP相比,可以减少延迟。 从表面上看,QUIC 非常类似于在 UDP 上实现的 TCP + TLS + HTTP / 2。 由于 TCP 是在操作系统内核和中间件固件中实现的,因此对 TCP 进行重大更改几乎是不可能的。 但是,由于 QUIC 建立在 UDP 之上,因此没有这种限制。
特性
减少连接建立时间
- HTTP:建立一个连接需要进行 1.5 RTT TCP 握手。如果使用 HTTPS,还需要 2 RTT 握手。
- QUIC:客户端第一次连接到服务器时,客户端必须执行 1 RTT 握手,以获取完成握手所需的信息完成密钥交换。 下次客户端连接时,它可以使用先前连接中的缓存凭据立即将加密的请求发送到服务器,实现 0RTT 连接。
改善拥塞控制
QUIC具有可插拔的拥塞控制,并且为 TCP 提供比拥塞控制算法更丰富的信息。
QUIC 每个分组(原始分组和重传分组)携带新的序列号。这允许 QUIC 发送器区分重传的 ACK 和原始的 ACK ,并避免 TCP 的重传模糊问题。 QUIC ACK 还明确地携带接收分组与其发送的确认之间的延迟,以及单调递增的序列号。这允许精确的往返时间计算。
QUIC 的 ACK 帧支持多达256个 NACK 范围,因此 QUIC 比 TCP(带有SACK)更能恢复重新排序,并且当重新排序或丢失时能够在线路上保留更多字节。客户端和服务器都可以更准确地了解对等方收到的数据包。
没有队头阻塞的多路复用
- HTTP:队头阻塞是 HTTP/2 多路复用的一个缺陷。HTTP/2 在一个 TCP 连接上同时发送3个stream,其中第2个stream丢了一个包,TCP为了保证数据可靠性,需要等到发送端重传丢失的数据包并且接收为止,即使其他流的数据包已经到达并且正在缓冲区中等待。
- QUIC:每个 HTTP 流是相互独立的,当发生丢包的情况,仅影响发生丢包的流,不会影响别的流数据的处理。
向前纠错
- TCP:发生丢包时需要等待发送端重传。
- QUIC:为了在不等待重传的情况下从丢失的分组中恢复丢包,QUIC 使用了FEC(前向纠错码)来恢复数据。FEC 采用简单异或的方式,每发送一组数据,包括若干个数据包后,并对这些数据包依次做异或运算,最后的结果作为一个 FEC 包再发送出去。如果组中的一个包丢失,则可以从 FEC 包和组中的剩余包恢复该分组的内容。多个包丢失不能恢复。
连接迁移
- TCP:连接如果发生 IP 或者端口修改,连接将不再有效。
- QUIC:连接由客户端随机生成64位连接 ID 标示。当发生 IP 或者端口修改时,QUIC 可以继续使用旧连接不中断请求。
科普:QUIC协议原理分析
试图取代 TCP 的 QUIC 协议到底是什么?
QUIC
WebSocket
WebSocket 的发明主要是因为 Web 端没有好的方式进行即时双向通信。
连接建立
WebSocket使用 HTTP 协议进行连接建立,之后通过 WebSocket 的二进制分帧进行数据传输。
WebSocket