[技术向] OSI 模型概览
OSI (开放式系统互联) 模型的 7 个层次:

从下至上的网络层次, 实际上是物理空间 (具象) 到虚拟空间 (抽象) 的逐级过渡, 使得现实世界的物理因素对于互联网应用而言几乎完全透明.
从 TCP/IP 视角看各层协议:

常见的应用与对应协议:

DNS
域名系统 (Domain Name System) 的作用是将主机名字转换为 IP 地址, 它被设计为一个联机分布式数据库系统, 解析域名的工作由许多域名服务器共同完成. 域名服务器是具有层次的, 反映在域名结构上.

主要有 4 类域名服务器:
根域名服务器: 不会直接将待查询的域名转换为 IP 地址, 而是告诉本地域名服务器下一步应当找哪个顶级域名服务器, 采用任播 (anycast) 技术, 每个 IP 有多个镜像.
顶级域名服务器: 管理在该顶级域名服务器注册的所有二级域名.
权限域名服务器: 负责一个地理区域内的查询.
本地域名服务器: 又称默认域名服务器, 离用户较近.
为了提高可靠性, 域名服务器会把数据复制到若干个服务器保存 (备份机制), 其中一个是主域名服务器, 其他的是辅助域名服务器. 主域名服务器定期将数据复制到辅助域名服务器中, 这一过程称为"区域传输", 使用 TCP 协议; 更改数据只能在主域名服务器中进行, 从而保证数据的一致性.
DNS 的域名解析过程:
主机向本地域名服务器采用递归查询 (一种视角), 若主机所询问的本地域名服务器不知道被查询的 IP 地址, 则本地域名服务器就以 DNS 客户的身份向其他根域名服务器继续发出查询请求.
本地域名服务器向根域名服务器大多数采用迭代查询, 根域名服务器要么给出所要查询的 IP 地址, 要么告诉本地域名服务器下一步应向哪个域名服务器查询, 以此类推.

主机 m.xyz.com 先向本地域名服务器 dns.xyz.com 进行递归查询;
本地域名服务器采用迭代查询, 先向最近的根域名服务器查询;
根域名服务器告诉本地域名服务器, 下一步应查询顶级域名服务器 dns.com (给出 IP 地址)
本地域名服务器向 dns.com 查询
顶级域名服务器告诉本地域名服务器, 下一步应查询权限域名服务器 dns.abc.com
本地域名服务器向 dns.abc.com 查询
权限域名服务器给出所查询的 IP 地址
本地域名服务器将查询结果返回给主机 m.xyz.com
这个过程使用的是 UDP 协议, 另外, 为了提高查询效率, DNS 广泛使用高速缓存.
DNS 劫持又称域名劫持, 通过某些手段取得某域名的解析控制权 (比如把用户的 DNS 查询导向自己的服务器), 修改此域名的解析结果, 导致对该域名的访问由原 IP 地址转入到修改后的指定 IP.
HTTP
HTTP 指超文本传输 (Hypertext Transmission) 协议, 定义了浏览器如何向万维网服务器请求文档, 以及服务器如何将文档传送给浏览器. 它是面向事务的, 一系列的信息交换是一个不可分割的整体, 要么都完成, 要么都不进行.
客户端与服务器的每次交互都由一个 ASCII 码串构成的请求报文和一个"类 MIME"的响应报文组成.
HTTP 有以下特点:
无状态: HTTP 本身不规定服务器对用户的响应需要考虑之前的访问情况.
无连接: 虽然 HTTP 使用了 TCP 连接, 但连接的建立和维护不在 HTTP 的考虑范围内.
HTTP 状态码: https://www.runoob.com/http/http-status-codes.html
版本更新
[ HTTP/1.0 ] 每一次交互都需建立一个新的 TCP 连接, 三次握手 + 一次响应, 花费两倍 RTT (往返时间).
[ HTTP/1.1 ] 使用持续连接, 又称长连接, 令 TCP 连接建立后可保留一段时间 (保活, Keep-Alive), 下一次交互时复用, 持续连接有非流水线和流水线两种工作方式.
非流水线: 客户端收到响应后才能发出下一个请求, 因此每一次交互都要用去一个 RTT.
流水线: 客户端在收到响应之前可连续发送新的请求, 服务器亦可连续发回响应报文.
[ HTTP/2.0 ] 使用二进制分帧 (类似于分成报文或者分组), 可乱序发送, 改善了一应一答的低效模式, 并且可以通过同一个 TCP 连接并行发送请求.
[ HTTP/3.0 ] 改用 UDP, 更准确地说是 QUIC (Quick UDP Internet Connections), 这个协议本身集成了 TLS.

RESTful 是一种 HTTP API 的设计风格, 通常认为可以让接口更加清晰, 简洁.
比如, 请求使用"动词 + 宾语"的形式表示, 动词是 HTTP 方法, 宾语是 URL.

FTP
FTP 指文件传输协议, 适用于在异构网络中的任意计算机之间传送文件, 它屏蔽了各计算机系统的细节.
FTP 是基于 TCP 的, 因为要保证传输的可靠性. 一个 FTP 服务器进程可同时为多个客户进程提供服务, 主进程负责接收新的请求, 另有若干从属进程负责处理单个请求. 每个 FTP 客户端都会和服务器建立两个 TCP 连接.
控制连接: 在整个会话期间一直打开, 服务器的控制进程在接收到客户端的文件传输请求后, 就创建数据传送进程, 在传输过程中, 双方可利用控制连接对传输进行控制, 如请求终止传输.
数据连接: 负责传输文件数据.
DHCP
DHCP 指动态主机配置协议, 提供了即插即用连网的机制, 允许一台计算机加入新的网络和获取 IP 地址而不用手工参与, 涉及到单播和广播的配合使用.
从 DHCP 获取的 IP 地址一般租期为 8 个小时, 为了保持通信的畅通, 一般客户端在租期还剩余一半的时候, 会和 DHCP 服务器进行租期延长对话, 正常情况下都会续租成功.
SSL
SSL 指安全套接字层 (Secure Socket Layer).
握手过程分 4 个阶段:

客户端发送 Hello 消息, 包含会话 ID、支持的版本号、支持的密码套件、支持的压缩算法, 以及一个随机数 CR, 服务器也发送相应的 Hello 消息, 包含一个选择好的版本号、密码套件、压缩算法, 以及一个随机数 SR.
服务器将一系列证书发给客户端, 使客户端能用服务器证书中的服务器公钥认证服务器, 服务器也可能会要求对客户端进行验证.
客户端生成一个预备主密钥 PM, 并用服务器在上一阶段发过来的公钥进行加密, 再发送给服务器, 如果服务器要求客户端证明自己, 还需要发送证书信息.
客户端使用服务器的公钥对 CR、SR、PM 进行一系列加密和哈希运算, 生成主密钥 M, 并告知服务器切换密钥,服务器也进行相同的操作,握手结束。
握手过程结束后就切换到应用数据的交换阶段,此时双方都用 M 进行对称加密.
如何保证 SSL 证书的合法性?
发送端会对数字证书的明文做一次哈希运算, 再使用 CA 颁发的私钥进行加密, 作为"数字签名". 对接收端来说, 数字证书和 CA 的公钥是可见的, 因此在收到数字签名后, 会使用公钥进行解密, 就可以验证"对方是否持有 CA 私钥"这一事实.
TLS
TLS 指传输层安全 (Transport Layer Security) 协议, 是针对 SSL 3.0 改进的版本, 使用不同的加密算法.
TLS 由记录协议和握手协议组成.
TCP
TCP 指传输控制 (Transmission Control) 协议, 是一种面向连接的、可靠的、基于字节流的传输层通信协议, 拥有数据分片、到达确认、超时重发、滑动窗口、失序处理、重复处理、数据校验机制.
头部信息:

前 20 个字节是固定的, 后有 4n 字节是根据需要而增加的选项:
序号: 用于对字节流进行编号, 例如, 序号 301 表示第一个字节的编号为 301, 若携带的数据长度为 100 字节, 那么下一个报文段的序号应为 401
确认号: 期望收到的下一个报文段的序号, 例如 B 正确收到 A 发送来的一个报文段, 序号为 501, 携带的数据长度为 200 字节, B 发送给 A 的确认报文段中确认号就为 701
数据偏移: 数据部分距离报文段起始处的偏移量, 即头部消息的长度
确认 ACK: 当 ACK=1 时确认号字段有效, 连接建立后的所有报文段必须把 ACK 置为 1
同步 SYN: 在连接建立时用来同步序号, 当 SYN=1, ACK=0 时表示一个连接请求报文段, 若对方同意建立连接, 则响应报文中 SYN=1, ACK=1
终止 FIN: 当 FIN=1 时, 表示此报文段的发送方的数据已发送完毕, 要求释放连接
窗口: 窗口值作为接收方让发送方设置其发送窗口的依据, 之所以要有这个限制, 是因为接收方的数据缓存空间是不断变化的
连接管理
TCP 有十种连接状态:
LISTEN (监听连接请求) / SYN_SENT (请求连接) / SYN_RECV (收到连接请求并返回响应) / ESTABLISHED (连接建立)
FIN_WAIT1 (请求断开连接) / CLOSE_WAIT (不再接收数据) / FIN_WAIT2 (不再发送数据) / LAST_ACK (连接中的所有数据已经发送完毕) / TIME_WAIT (连接释放倒计时) / CLOSED (关闭连接)
连接阶段分为 3 步, 又称"三次握手":

首先 B 处于 LISTEN 状态, 监听客户端的连接请求
A 向 B 发送连接请求报文 (SYN=1 & ACK=0) 并选择一个初始的序号 x, 此时 A 处于 SYN-SENT 状态
B 收到连接请求报文, 如果同意连接, 就向 A 发送连接确认报文 (SYN=1 & ACK=1), 确认号为 x+1, 同时也选择一个初始的序号 y, 此时 B 处于 SYN-RCVD 状态
A 收到 B 的连接确认报文后, 还要向 B 发出确认, 确认号为 y+1, 序号为 x+1
B 收到 A 的确认后, 连接建立, 双方都处于 ESTABLISHED 状态
第三次握手是为了防止失效的连接请求到达服务器, 让服务器建立了一个多余的连接.
客户端发送的连接请求如果在网络中滞留, 会隔很长一段时间才能收到服务器发回的确认, 在这段时间里, 客户端可能触发超时重传, 重新请求连接. 但是之前滞留的连接请求最后还是会到达服务器, 如果不进行三次握手, 那么服务器就会打开两个连接; 第三次握手的意义在于, 客户端可以忽略服务器对滞留连接请求的连接确认, 服务器也就不会打开第二个连接.
连接的释放则分为 4 步, 又称"四次挥手":

A 发送连接释放报文段 (FIN=1), 序号为 u, 处于 FIN-WAIT-1 状态
B 收到后发出确认, 确认号为 u+1, 序号为 v, 此时 B 处于 CLOSE-WAIT 状态, A 处于 FIN-WAIT-2 状态, B 能向 A 发送数据, 反之不行
B 不再需要连接时, 发送连接释放报文 (FIN=1), 变为 LAST-ACK 状态
A 收到后发出确认, 进入 TIME-WAIT 状态, 等待 2 MSL (最大报文存活时间) 后自动释放连接
B 收到 A 的确认后释放连接
之所以要分 4 步, 是为了让服务器端发送还未传送完毕的数据.
TIME-WAIT 的作用:
确保最后一个确认报文能够到达, 如果 B 没收到 A 发送来的确认报文, 会重新发出连接释放请求
等待本连接之前产生的所有报文都从网络中消失, 使得下一个新的连接不会出现旧的连接请求报文
各种状态之间的转换总结如下:

在连接的任一阶段, 如果服务端进程被关闭了, 但是服务器没有宕机, 那么内核在回收 TCP 资源的时候会主动发起第一次挥手, 后面的流程照常进行. 如果服务器宕机了, 分两种情况:
客户端需要发送数据, 就会产生多次超时重传 (指数退避), 重传达到一个阈值后 (默认是 15) 会自动断开连接.
客户端不需要发送数据, 如果没有开启 TCP 保活机制, 那么这一端的连接会一直保留; 如果开启了保活机制, 客户端会定时发送心跳检测报文, 产生跟 1 类似的流程.
可靠传输
TCP 使用滑动窗口协议来保障传输的可靠性.

窗口是缓存的一部分, 用来暂时存放字节流. 发送方和接收方各有一个窗口, 接收方通过 TCP 报文段中的窗口字段告诉发送方自己的窗口大小, 发送方以此为根据, 设置自己的窗口大小. 发送窗口内的字节都允许被发送, 接收窗口内的字节都允许交付给上层应用.
什么时候产生窗口的滑动?如果发送窗口左部的字节已经发送并且收到了确认, 那么发送方就将发送窗口向右滑动, 直到左部第一个字节不是已发送并且已确认的状态,接收窗口的滑动类似, 接收窗口左部字节已经发送确认并交付上层应用, 就向右滑动.
接收窗口只会对窗口内最后一个按序到达的字节进行确认, 例如接收窗口已经收到的字节为 {31, 34, 35}, 其中 {31} 按序到达, 而 {34, 35} 不是, 因此只对字节 31 进行确认, 发送方得到一个字节的确认之后, 就知道这个字节之前的所有数据已经被接收.
流量控制
流量控制是为了控制发送方的发送速率, 保证接收方来得及接收.
TCP 头部的窗口字段可以用来控制发送方窗口大小, 若设置为 0, 对面就不能发送数据.

假如接收方的接收缓存已满, 发送了一个零窗口的报文段, 等接收缓存有空余后又发送一个窗口字段为正的报文段, 但在传输过程中丢失了, 那么 (在没有额外机制的情况下) 双方会一直等待下去. 为了避免这种局面, 每一个 TCP 连接都有一个持续计时器, 只要有一方收到零窗口通知, 就启动该计时器, 到期发送一个零窗口探测报文段, 对方返回最新的窗口值.
拥塞控制
流量控制是点对点通信量的控制, 拥塞控制是全局性的控制. 所谓拥塞, 是说在某个时间段中, 对网络中某一资源的需求超过了该资源的可用部分 (请求量太大), 导致网络性能下降. 在无拥塞控制的情况下, 负载增大到一定程度时, 网络的吞吐量将随负载的增大而下降, 极端情况下, 网络会瘫痪.

TCP 通过四个算法来进行拥塞控制: 慢开始, 拥塞避免, 快重传, 快恢复.
发送方需要维护一个叫做拥塞窗口 (cwnd) 的状态变量, 代表可发送数据的上限.
为了便于讨论, 做如下假设:
接收方有足够大的接收缓存, 因此不会发生流量控制
虽然 TCP 的窗口基于字节, 但是这里以报文段作为窗口的单位
慢开始和拥塞避免
发送的最初执行慢开始, 令 cwnd = 1, 发送方只能发送 1 个报文段, 当收到确认后, 将 cwnd 加倍, 因此之后发送方能够发送的报文段数量为: 2, 4, 8...
由于慢开始每个轮次都将 cwnd 加倍, 这样会让发送速度呈指数增长, 网络拥塞的可能性也就更高, 于是设置一个慢开始门限 ssthresh, 当 cwnd >= ssthresh 时, 进入拥塞避免阶段, 每个轮次只将 cwnd 加 1.
如果出现了超时, 则令 ssthresh = cwnd / 2, 然后重新执行慢开始.
快重传和快恢复
在接收方, 要求每次收到报文段都对最后一个已收到的有序报文段进行确认, 例如已经接收到 M1 和 M2, 此时收到 M4, 应当发送对 M2 的确认.
在发送方, 如果收到三个重复确认, 那么可以认为下一个报文段丢失, 此时执行快重传, 立即重传下一个报文段 (而不是等待超时), 例如收到三个 M2 的确认, 则认为 M3 丢失, 立即重传 M3.
在这种情况下, 也令 ssthresh = cwnd / 2, 但会跳过慢开始阶段 (只是丢失了个别报文段, 不大可能是网络拥塞), 直接令 cwnd = ssthresh, 这就是快恢复.
慢开始和快恢复的 "快/慢" 指的是 cwnd 的设定值, 而不是 cwnd 的增长速率, 慢开始 cwnd 设定为 1, 而快恢复 cwnd 设定为 ssthresh.
上述四个算法的搭配关系如下:

TCP 中存在 4 种计时器:
重传计时器 (Retry)
保活计时器 (KeepAlive)
坚持计时器 (Persistence)
超时计时器 (Timeout)
UDP
UDP 指用户数据报 (User Datagram) 协议, 是面向报文的、无连接的、不保证可靠的, 常用于实时通信.
UDP 的头部信息相较于 TCP 要少很多, 只有 8 个字节, 包括源端口、目的端口、长度、检验和, 还有 12 个字节"伪首部"是为了计算检验和临时添加的, 不会被传输.

TCP 和 UDP 的区别:
IP
IP 指网际协议 (Internet Protocol), 拥有许多配套协议. 它的最大作用是屏蔽了不同的 (异构) 局域网络的内部细节. IP 协议头部长度在 20 ~ 60 字节之间.

当某个设备切换了 IP 的时候 (比如手机从 WIFI 变成使用流量), 原有的连接状态会发生什么改变?
IP 的变动是会引起 TCP 连接重置的, 但是如果使用了 HTTP 3.0, 就不存在这个问题 (见上文, 3.0 基于 UDP).
ICMP
ICMP 指网际控制报文协议, 允许主机或路由器报告网际层的异常情况, 属于 IP 层, 不过报文封装在 IP 数据报中, 分为差错报告、询问两种类型.

改变路由 (Redirect) 的机制是: 主机刚开始工作时, 一般都在路由表中设置默认路由器的 IP 地址, 会先把数据报传给默认路由器, 这个默认路由器通过和其他路由器交换信息, 知道到每一个目的网络的最佳路由. 如果默认路由器发现主机发往目的地址 A 的最佳路由应经过同一网络的路由器 R, 就会向主机发送"改变路由"差错报告报文, 主机会在路由表中新增一项: 到地址 A 应经过路由器 R.
分组网间探测 PING 就是用 ICMP 完成的, 这是一个应用层直接使用网络层的例子, 运行 PING 会连续发送 4 个 ICMP 回送 (Echo) 请求报文到目标主机, 若服务器正常工作且不拒绝探测, 就会发送 ICMP 回送回答报文, 根据往返报文上的时间戳即可进行统计.
IGMP
IGMP 指网际组管理协议, 用于让路由器知道多播 (multicast) 组的成员信息, 多播技术用于在一对多的通信中节省网络资源, 服务器只需发送一次分组, 路由器在转发时会对分组进行拷贝, 发往不同的局域网, 当分组到达局域网后, 通过硬件多播到达所有成员.

多播数据报的目的地址写入的是多播组的标识符 (毕竟不可能把所有成员的 IP 地址写上去), 然后将这个多播组的成员 IP 地址与这个标识符关联起来. 标识符其实就是 IP 地址中的 D 类地址 (前四位 1110, 范围是 224.0.0.0 ~ 239.255.255.255), 共可标志 2^28个多播组.
IGMP 的工作可分为两个阶段:
当某台主机加入新的多播组时, 该主机向多播地址发送一个 IGMP 报文, 声明自己要成为该组成员, 路由器会使用"多播路由选择协议"将该组成员关系转发给其他多播路由器.
组成员关系是动态的, 本地的多播路由器会周期性探询局域网上的主机, 并不需要准确记录各主机, 只需确定该局域网上存在有一台主机在该多播组中即可.
ARP
ARP 是地址解析协议, 用于根据 IP 地址解析出数据链路层的硬件地址, 解决同一局域网上的主机或路由器的 IP 地址和硬件地址的映射问题.

在浏览器访问一个 URL, 涉及到的协议:
DNS (发起域名解析请求)
DHCP (如果当前主机没有 IP, 需要向 DHCP 服务器获取, 一般是路由器)
ARP (获取路由器的 MAC 地址)
NAT (网络地址转换/端口映射, 由所处局域网的路由器完成)
IP、TCP、HTTP/HTTPS (网际层到应用层的装包)