数据链路层
帧
成帧方法
比特填充法
标志字段:01111110,用来标记帧首尾。
规则:发送方,只要数据里连续出现 5 个 1,自动插入 1 个 0。
接收方:收到连续 5 个 1,检查下一位:
- 如果是 0 → 删除这个 0(还原数据)
- 如果是 1 → 再看后面:是 0 代表帧结束;是 1 代表错误。
保证数据永远不会出现 6 个连续 1,避免和标志字段混淆。
以太网帧
组成
- 前导码 (Preamble):7 字节
10101010+ 1 字节10101011。作用:同步时钟,标记帧开始,不属于链路层帧的数据部分。 - 目的 MAC 地址 (6B):接收方网卡 MAC
- 源 MAC 地址 (6B):发送方网卡 MAC
- 类型字段 (2B):标识上层是什么协议(
0x0800=IP;0x0806=ARP) - 数据载荷:最小 46 字节,最大 1500 字节(MTU=1500 字节)
- FCS(帧校验序列):校验范围:目的 MAC、源 MAC、类型、数据、填充。不校验前导码。
stop and wait control ARQ
从起点发送一个 Frame 到终点,如果收到了就返回一个 Ack。起点会等待收到上一个 Frame 的 ack 才会去发送下一个Frame
流程
- S 发送 DATA0,启动定时器
- R 收到 DATA0,回复 ACK0
- S 收到 ACK0,发 DATA1,重启定时器
- R 收到 DATA1,回复 ACK1
- 若 DATA0 丢失,S 定时器超时,重传 DATA0;R 收到重复 DATA0,丢弃数据,重发 ACK0
Go-Back-N
连续发送窗口内多个帧;收到 ACK 才滑动窗口;一旦丢帧,丢帧及其后面所有已经发出去的帧全部重传
流程
- S 一次性连续发 DATA0、DATA1、DATA2、DATA3
- DATA2 在链路丢失
- R 收到 DATA0 → ACK0;收到 DATA1 → ACK1;收到 DATA3,但是 R 期望 DATA2,直接丢弃 DATA3,不发 ACK3
- S 的 DATA2 定时器超时,回退,重传 DATA2、DATA3
- R 收到 DATA2,回复 ACK2,窗口继续滑动
Selective Repeat SR 选择重传
连续发送;只重传出错 / 丢失的那一帧,其余正确帧先缓存,不丢弃。发送窗口、接收窗口都 > 1
流程
- S 发送 DATA0,DATA1,DATA2
- DATA1 丢失
- R 收到 DATA0,上交上层,返回 ACK0;收到 DATA2,存入接收缓冲区,返回 ACK2(不会丢弃 DATA2)
- S 检测 DATA1 超时,仅重传 DATA1
- R 收到 DATA1,此时 0、1、2 帧全部集齐,一次性交付上层
网络层
IP 协议
协议头
IP 地址分类
- A 类:0 开头,1~126;默认掩码 / 8
- B 类:10 开头,128~191;默认掩码 / 16
- C 类:110 开头,192~223;默认掩码 / 24
- D 类:1110 开头,224~239,组播
- E 类:保留
路由
路由器工作在网络层:
- 接收帧 → 剥掉链路层头部 → 读取 IP 首部
- 查询路由表:目的 IP 匹配路由条目,得到下一跳
- 重新封装新的链路层帧,转发出去
IPv6
IPv6 与 IPv4 区别
- IPv4:32bit,点分十进制
192.168.1.1 - IPv6:128bit,分成 8 组,每组 16bit,十六进制,用冒号隔开
常用指令
traceroute
# -n 不做反向域名解析(最常用)traceroute-nwww.baidu.com# -I 使用ICMP发包,类似Windows tracert,解决UDP被防火墙拦截问题traceroute-Iwww.baidu.com# -w 设置超时等待时间,单位秒traceroute-w2www.baidu.com# -m 设置最大跳数(默认30跳)traceroute-m20www.baidu.com传输层
TCP
报文结构
- 源端口号 16 bit 发送方端口
- 目的端口号 16 bit 接收方端口
- 序列号 seq 32 bit 本报文段数据第一个字节的编号。用来字节流编号,实现顺序、重传
- 确认号 ack 32 bit 期望收到对方下一个字节的序号。只有ACK=1时才有效,ack = 收到 seq + 数据长度
- 数据偏移 4 bit TCP 头部长度,单位:4 字节。
例:值为 5 → 5×4=20 字节(无选项),最大 15 → 60 字节 - 保留位 6 bit 保留,现在一般置 0
- 控制标志位 6 bit 6 个标志位,可组合
- 窗口大小 window 16 bit 接收窗口,流量控制。告诉对方:我现在最多还能收多少字节
- 校验和 checksum 16 bit 校验范围:TCP 头部 + TCP 数据 + 伪首部
- 紧急指针 urgent 16 bit URG=1生效。偏移量,指向紧急数据末尾,紧急数据优先交付
- 选项 options 可变(0~40 字节) 常用:MSS、窗口扩大、时间戳、SACK
- 填充 padding 可变 补 0,保证头部 4 字节对齐
- 数据 payload 可变 应用层数据,可空(如 SYN、ACK 报文)
控制标志位
- URG(Urgent 紧急):
URG=1,紧急指针有效,紧急数据优先上交应用层,不用等缓冲区满 - ACK(Acknowledge 确认):
ACK=1,确认号才有效。连接建立后所有报文 ACK 都置 1 - PSH(Push 推送):接收方收到后,立即把缓冲区数据交给应用层,不缓存
- RST(Reset 重置):复位连接。端口不存在、异常连接,直接断开
- SYN(Synchronize 同步):建立连接,握手用。SYN 报文不带数据,但消耗一个序列号
- FIN(Finish 结束):释放连接。FIN 报文不带数据,消耗一个序列号
三次握手,四次挥手
三次握手
四次挥手
流程
CLOSE_WAIT 和 TIME_WAIT
- 客户端(主动关闭)→ 发 FIN → 服务端
- 服务端收到 FIN → 回 ACK → 进入CLOSE_WAIT
- 服务端调用 close () → 发 FIN → 客户端
- 客户端收到 FIN → 回 ACK → 进入TIME_WAIT,等待 2MSL 后彻底关闭
为什么等待 2MSL
5. 保证最后这个 ACK 能到达对端;如果 ACK 丢了,对方会重发 FIN,我可以再次回复 ACK。
6. 等待网络上残留的旧数据包消失,防止新连接收到旧报文。
滑动窗口
- 发送窗口:发送方维护
- 允许发送,但还没收到 ACK 的数据范围
- 上限 = 接收方通告窗口
rwnd(接收方剩余缓冲区大小),同时还要受拥塞窗口cwnd限制,取较小值
- 接收窗口(rwnd,通告窗口):接收方维护
- 接收缓冲区空闲容量,放在 TCP 头部
Window字段,随 ACK 发给发送方 - 用来流量控制:防止发送方发太快,把接收方缓冲区撑爆
- 接收缓冲区空闲容量,放在 TCP 头部
拥塞控制
- 拥塞窗口(cwnd),发送方维护,代表网络允许发多少字节
慢开始
初始:cwnd = 1 MSS(MSS:最大报文段长度)
规则:每收到一个 ACK,cwnd 翻倍,指数增长
- 当
cwnd < ssthresh:慢启动阶段,指数涨 - 当
cwnd >= ssthresh:退出慢启动,进入拥塞避免
拥塞避免
规则:每经过 1 个 RTT,cwnd += 1 MSS,线性增长,慢慢试探网络上限,不再暴涨
快重传
触发条件:收到3 个重复 ACK
含义:报文段丢了,但网络还没完全堵死(不是超时)
动作:不等超时定时器到期,立刻重传丢失报文
快恢复
收到 3 个重复 ACK 后:
ssthresh = cwnd / 2cwnd = ssthresh- 进入拥塞避免,cwnd 线性增长,不回到慢启动
超时的处理
ssthresh = cwnd / 2cwnd = 1 MSS- 重新走慢启动
UDP
头部结构
- 源端口:可选,不填就是 0
- 目的端口:必须,用来定位应用进程
- 长度:UDP 头部 + 数据总长度,最小 8(只有头部)
- 校验和:可选,校验头部 + 伪首部 + 数据,检测是否损坏,出错直接丢弃
核心特点
- 无连接:通信前不需要建立连接(没有三次握手),发数据前不用协商。开销极小。
- 不可靠交付:丢包就丢了,不会通知发送方。
- 不确认 ACK
- 不重传丢包
- 不排序,收到什么顺序就上交应用层
- 没有流量控制、拥塞控制
- 面向报文
应用层给 UDP 一个报文,UDP 原样打包下发;接收方一次完整交付一个报文。不会拆分 / 合并报文。
常用指令
netstat
查看本机网络连接、监听端口、路由、协议统计
核心参数
- -a,显示所有 socket:包含监听 LISTEN 和已建立连接
- -n,数字形式显示 IP / 端口,不做域名解析,速度快,必加
- -t,只看 TCP 连接
- -u,只看 UDP 连接
- -l,只看正在监听的端口(服务等待接入)
- -p,显示PID 和进程名;需要 root 权限
输出字段解释
- Proto:协议 tcp /udp
- Recv-Q:接收队列,等待应用读取的数据字节数;非 0 代表应用读慢,阻塞
- Send-Q:发送队列,待发送出去的数据字节数;非 0 代表发包受阻
- Local Address:本机 IP: 端口
0.0.0.0:8080:监听本机所有网卡的 8080 端口127.0.0.1:8080:仅本机回环可访问,外部无法连接
- Foreign Address:对端 IP: 端口
- State:TCP 连接状态(UDP 无状态)
- PID/Program name:占用这个 socket 的进程 ID 和程序名
应用层
HTTP
什么是 HTTP
http是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应
HTTP 1.0
底层:TCP,文本协议
- 默认短连接:一次请求 → 一次响应 → 立刻关闭 TCP 连接。
- 缺点:每次请求都要 TCP 三次握手 + 四次挥手。网页有多个资源(图片、js、css),就要反复建连,延迟很高。
- 可选
Connection: keep-alive开启长连接,但不是默认行为。
HTTP 1.1
底层:TCP,文本协议
- 默认开启 keep-alive 长连接:一条 TCP 连接可以连续发送多次请求,不用每次都断开重建。
- 支持管线化(pipeline):理论上可以连续发送多个请求,不用等前一个响应回来。
ps:管线化浏览器几乎没有实现,因为响应必须按请求顺序返回。如果第一个请求很慢,后面所有响应都得排队,依然阻塞
核心痛点
请求层面的队头阻塞
一条 TCP 长连接上,请求必须串行处理
举例:同一个 TCP 连接发两个请求:请求 A(大图片慢)、请求 B(小 js 很快)
必须等 A 响应完整返回之后,服务端才能返回 B。A 卡住,B 就卡住Header 头部冗余
每次请求,完整带上所有 Header:Host、User-Agent、Cookie。
Cookie 可能每次重复携带大量数据,带宽浪费严重。
HTTP 2
- 目标:解决 HTTP/1.1 的请求队头阻塞、头部冗余问题。底层仍然是 TCP
- 核心改动:二进制帧 + 流(Stream)
HTTP/2 不再传输文本字符串,把报文拆成二进制帧
- 帧:最小传输单元,有类型、长度、流 ID;
- Stream(流):一条 TCP 连接内部的独立逻辑通道,用流 ID 区分。
- 多路复用:单条 TCP 连接,可以并行发送多个 Stream(多个请求响应)
同一个 TCP 里,请求 A、请求 B 可以同时发;响应 B 先准备好,可以先返回,不用等 A。
关键特性
- HPACK 头部压缩
维护静态字典 + 动态字典。重复的 Header(比如 Cookie、Host)不用每次完整传输,只传索引,大幅减少头部体积。 - 流优先级
客户端给 stream 设置权重,告诉服务端优先返回 css、html 这种关键资源。 - Server Push 服务端推送
服务端预判浏览器后续需要的资源,主动推送给客户端,不用等客户端发起请求。
核心痛点
TCP 层面的队头阻塞仍然存在
多路复用是 HTTP2 应用层逻辑,底层还是 TCP。
TCP 特性:有序、可靠传输。只要一个数据包丢失,TCP 就会暂停所有数据,等待丢失包重传
举个例子:
单 TCP 连接,同时跑 Stream A、Stream B。
- Stream A 的某个数据包丢包;
- TCP 必须等待这个包重传成功;
- 在等待期间,哪怕 Stream B 的数据已经收到,也不能向上交付给应用;
与 HTTP 1.1 的区别:
- HTTP1.1:队头阻塞发生在请求排队;
- HTTP2:请求可以并行,但只要 TCP 丢包,全部流一起阻塞。
HTTP 3
目标:干掉 HTTP2 残留的TCP 层面队头阻塞
底层不再使用 TCP,改用 QUIC 协议,QUIC 跑在 UDP 之上。HTTP 上层语义依旧不变
为什么不用 TCP?
- TCP 是操作系统内核实现的协议。我们无法修改 TCP 重传、拥塞控制、丢包处理逻辑。
- QUIC 基于 UDP,在用户态实现完整传输协议,可以自定义重传、连接、流机制,快速迭代。
核心能力
真正消除队头阻塞
QUIC 连接内部,同样有多个独立 Stream。
每个流独立管理丢包。一个流丢包,只阻塞当前这个流,其他流不受任何影响
例子:Stream A 丢包,只等 A 重传;Stream B 的数据正常接收、正常交付上层更快握手
- TCP:3 次握手;再加 TLS 握手,一共 2-RTT;
- QUIC:把传输握手和 TLS 加密握手合并。首次建立 1-RTT;客户端曾经访问过服务端,下次访问可以 0-RTT 直接携带业务数据,减少延迟。
内置 TLS 加密
- QUIC 报文本身强制加密,不存在明文 HTTP3。HTTP2 还有 h2c 明文版本
缺点
- UDP 容易被防火墙、运营商策略拦截。部分内网 / 老旧网络会屏蔽 UDP 大包,导致 HTTP3 无法建立连接,客户端自动降级 HTTP2/HTTP1.1
- 部署复杂度更高,CDN、服务端需要额外支持 QUIC
QUIC
基于 UDP、内置 TLS1.3 的可靠传输协议
握手
QUIC把传输握手 + TLS 密钥协商合并成一套流程,不再分层分开握手
- 首次新连接:1-RTT:Client → Server(携带握手信息);Server → Client(证书 + 密钥材料),之后双方就可以发业务数据。
- 会话复用(0-RTT):客户端之前连过该服务,缓存服务端密钥;第一个包就直接带上业务数据,不需要等待往返,适合移动端、短连接网页场景。
HPACK
HPACK 是HTTP/2 专用头部压缩算法,解决 HTTP1.1 每次请求完整传输全部 Header,大量重复字段(Cookie、User-Agent、:method、:path)浪费带宽的问题
核心组件
- 静态表
- 预定义,一共 61 条,只读,连接建立之初客户端和服务端双方都自带。
- 存放全网最高频 HTTP 头部(含 HTTP2 伪头部
:method:path:status) - 只要头部键值刚好匹配静态表,只需要传输一个索引号,不需要传输完整字符串
- 例如
index=2 →:method: GET
index=4 →:path: /
index=8 →:status:200
- 动态表
- 连接内动态维护,初始为空,客户端和服务端双方必须同步维护同一张表。
- 规则:FIFO 先进先出。新的头部加到表头;表满了,淘汰最老条目。
- 作用:本次 TCP 连接中新出现、不在静态表里的 Header(例如自定义 Cookie、Host),第一次传输完整内容,并且存入动态表;后面再出现,直接传索引号。
- 静态 Huffman 编码
- HPACK 自带一套固定的 Huffman 码表,对头部字符串内容做压缩。
- 当头部不在静态表、也不在动态表,原始字符串会先用这套 Huffman 压缩,减少字节。
编码模式
- 索引头部(Indexed Header Field)
直接引用静态 / 动态表索引。只传数字,压缩率最高。 - 字面头部,增量索引(Literal Header Field with Incremental Indexing)
头部是新的,不在表里;传输字符串,同时存入动态表,供后续复用。 - 字面头部,不存入动态表
传输字符串,不加入动态表,一次性使用。适合一次性、不会重复出现的 header,避免浪费动态表空间。
缺陷
HPACK 的动态表更新是强时序依赖,解码后面的 Header 块,必须保证前面所有动态表更新指令全部收到并处理完成,因此会存在队头阻塞问题
假设:StreamA 的 header 负责更新动态表,丢包延迟到达;StreamB 的 header 引用了动态表里 A 新增的条目。→ StreamB 拿到 header 帧,但动态表还没更新完成,无法解码→ StreamB 被阻塞
与 QPACK 区别
- QPACK 静态表为 91 条,扩充更多常用 header
- QPACK动态表更新放到独立控制流,和业务数据流解耦,只有引用该未就绪条目的流被阻塞,其他流不受影响
HTTP 与 HTTPS 的区别
- HTTP的URL以http://开头,而HTTPS的URL以https://开头
- HTTP是不安全的,而HTTPS是安全的
- HTTP标准端口是80,而HTTPS的标准端口是443
- 在OSI网络模型中,HTTP工作于应用层,而HTTPS的安全传输机制工作在传输层HTTP无法加密,而HTTPS对传输的数据进行加密
- HTTPS需要CA机构颁发的SSL证书,例如 globalsign,godaddy
- HTTP协议运行在TCP之上,所有传输的内容都是明文,HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的
- HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题
HTTPS
HTTP 的问题
- 明文传输:中间人抓包直接看到内容(账号密码)
- 无校验:传输数据可以被中间人随意篡改,客户端无法发现
- 不验证身份:你不知道连接的服务器是不是真的目标网站,容易访问钓鱼网站
HTTPS 的目标
加密(防窃听)+ 完整性校验(防篡改)+ 身份认证(防伪造)
对称加密
- 特点:加密和解密用同一个密钥;速度快,适合大量数据加密
- 缺点:密钥怎么安全传输?密钥一旦泄露全部数据暴露
非对称加密
- 公钥:公开,用来加密;私钥:服务器保管,用来解密
- 公钥加密的数据,只能私钥解密;私钥签名的数据,只能公钥验证
- 缺点:运算很慢,不适合加密大流量 HTTP 报文
数字证书
解决:公钥怎么证明它确实属于目标网站,而不是中间人伪造的公钥
- CA(证书颁发机构):可信第三方
- 数字证书内容:网站域名、网站公钥、证书有效期、CA 的数字签名
- 浏览器内置 CA 根证书列表
- 证书校验流程:
- 拿到服务器证书
- 用 CA 根证书里的公钥,验证 CA 签名是否合法
- 校验域名、有效期,通过则信任证书里的公钥
握手过程
- Client Hello
客户端发给服务端:支持的 TLS 版本、加密套件列表、随机数client random - Server Hello
服务端返回:选定的 TLS 版本、选定加密套件、随机数server random
同时下发数字证书 - 证书校验
客户端校验证书合法性(CA 签名、域名、有效期),失败直接告警 - 客户端生成预主密钥 Pre-Master Secret
客户端生成一段随机的 Pre-Master Secret,用服务器公钥加密发给服务器 - 双方各自计算会话密钥
客户端:client random + server random + Pre-Master Secret → 算出会话密钥
服务器:私钥解密拿到 Pre-Master Secret,同样三个值算出相同会话密钥 - Change Cipher Spec
双方通知对方:接下来通信全部使用协商好的对称密钥加密 - Finished
双方互相发送加密的握手摘要,验证握手过程有没有被篡改
工作流程总结
- DNS 解析拿到服务器 IP
- TCP 三次握手建立连接
- TLS 握手:协商加密套件、交换随机数、下发证书、验证证书、协商会话密钥
- HTTP 报文被会话密钥加密传输
- TLS 关闭
- TCP 四次挥手
DNS
核心作用:把人类好记的域名翻译成计算机能识别的 IP 地址
域名
分层结构,从右往左是根 → 顶级域 → 二级域 → 主机名
例如:www.baidu.com
com:顶级域名(.com/.org/.cn)baidu:二级域名www:主机名
DNS 服务器
- 根域名服务器:只返回顶级域服务器地址,不直接解析域名
- 顶级域服务器:返回该域名对应的权威 DNS 地址
- 权威域名服务器:保存某个域名的真实记录,最终给出域名对应的 IP
- 本地递归解析器:替客户端完整走完查询全过程,把结果返回给客户端
DNS 查询完整流程
- 浏览器先查浏览器缓存,有记录直接用;没有继续
- 查操作系统 hosts 文件,匹配则直接返回 IP
- 缓存 /hosts 无结果,操作系统向本地递归 DNS 服务器请求:查询
www.baidu.com的记录 - 本地 DNS 没有缓存,向根服务器迭代查询;根服务器回复:去找
.com顶级域服务器 - 本地 DNS 请求
.com服务器;.com服务器回复:去找 baidu 的权威 DNS - 本地 DNS 请求 baidu 权威服务器;权威服务器返回
www.baidu.com对应的 IP - 本地 DNS 把 IP 返回给操作系统,同时缓存这条解析结果(TTL 控制缓存有效期)
- 操作系统拿到 IP,浏览器通过 IP 建立 TCP 连接访问网站
资源记录类型
- A,IPv4 地址记录,域名→IPv4
- AAAA,IPv6 地址记录,域名→IPv6
- CNAME,别名记录,域名指向另一个域名
常用指令
dig
# 向本机配置的递归 DNS 发起递归查询,直接拿结果,会读取递归 DNS 缓存,看不到中间查询链路digwww.baidu.com# 跳过本机递归 DNS 缓存,dig 自己做迭代查询,从根服务器开始逐级查询,打印完整的委托链路digwww.baidu.com +traceDHCP
动态主机配置协议
作用:自动给内网里的设备分配 IP 地址、子网掩码、网关、DNS,不用你手动设置静态 IP
属于应用层协议,底层用UDP
流程
- Discover,客户端广播寻找 DHCP 服务器,源 IP:0.0.0.0,目的 IP:255.255.255.255
- Offer,DHCP 服务器收到后,从地址池挑一个空闲 IP,回复广播:我可以分给你这个 IP,附带掩码、网关、DNS、租期
- Request,客户端选择其中一个 Offer,再次广播,请求正式分配
- Ack,DHCP 服务器回复 Ack 广播,IP 分配生效,附带完整参数和租期
租期
DHCP 分配 IP 不是永久,是租约
- 租约到一半(50%):客户端单播向 DHCP 服务器续约;成功则租期刷新
- 续约失败,到租约 87.5%:再次广播尝试续约
- 完全到期还没续上:IP 释放,客户端重新走 DORA 流程申请新 IP
地址池
- 地址池(scope):DHCP 服务器预先划出一段 IP 范围,用来动态分配给客户端。
- 静态保留(地址绑定):把某个 MAC 地址固定绑定某个 IP,每次这个设备上线,永远拿到同一个 IP(类似静态 IP,但由 DHCP 统一管理)
- 排除地址:地址池里挖掉几个 IP,留给手动静态配置的服务器,防止冲突
ssh
ssh 属于应用层协议,底层是 TCP 协议
工作流程
- 握手与密钥交换
- 客户端连接服务器 22 端口,双方协商支持的加密算法、哈希算法
- 密钥交换(DH/ECDH),双方生成临时公私钥,算出一个共享会话密钥
- 服务器把自己的主机公钥发给客户端
- 整条通道已经加密,后面所有信息都是用计算得到的密钥进行对称加密传输
- 用户身份认证
- 密码认证:客户端把密码在加密隧道内发给服务端校验(密码本身不再明文)
- 公钥认证
- 客户端持有:私钥、公钥
- 服务端:把客户端公钥写入
~/.ssh/authorized_keys - 认证过程:
- 客户端向服务端发送自己公钥 ID
- 服务端生成随机字符串,发给客户端
- 客户端用私钥签名这个随机串,发回服务端
- 服务端用预先保存的客户端公钥验签,验证通过 → 登录成功
VPN
VPN 全称Virtual Private Network,虚拟专用网络
作用:在公网(互联网)上,建立一条加密的 “虚拟隧道”,把两个端点连接起来,让数据像跑在私有局域网里一样传输
流程
- 电脑访问公司内网,先经过 VPN 服务器进行加密
- VPN 服务器再将消息发送到目的 VPN 服务器
- 目的 VPN 服务器解密消息后再转发给实际的接收方
VPN 类型
- 站点-站点:两个异地的公司机房,路由器之间建立 IPsec 隧道,两个局域网互通,跨地域组成一个大私有网络
- 客户端-站点:手机 / 电脑获得公司内网 IP,隧道接入企业私网,就能访问公司 OA、数据库、文件服务器,和坐在公司局域网里效果一样
虚拟网络模型
NAT
把内网 IP + 端口映射成宿主机 IP + 端口
- 内网机器没有独立公网 IP,共用宿主机的 IP 上网
- 单向默认放行:虚拟机可以主动访问外网;外网不能直接主动访问虚拟机,虚拟机之间也不互通
桥接模式
虚拟网卡直接接入物理局域网,虚拟机和宿主机平级,相当于局域网里一台独立电脑
- 虚拟机从真实路由器 DHCP 拿 IP,和宿主机在同一个网段
- 拥有局域网独立 IP
- 虚拟机之间互通、虚拟机与宿主机也互通
仅主机模式
完全隔离,不经过物理网卡,没有外网出口,只在宿主机和一组虚拟机之间通信
- 不能访问外网
- 虚拟机之间可以互通、虚拟机与主机可以互通
面试题
TCP 和 UDP 的区别
- TCP:面向连接;UDP:无连接
- TCP:可靠传输(确认、重传、序号、校验);UDP:不可靠,尽最大努力交付
- TCP:首部开销大;UDP:首部固定 8 字节
- TCP:一对一;UDP:支持一对一、一对多、多对多
UDP 不可靠,为什么还要用 UDP
- 无需建立连接,延迟低;
- 首部小,开销小;
- 没有拥塞控制,不会因为网络拥塞降低发送速率,适合实时场景;
- 支持广播、组播;
TCP 报文头部结构
- 源端口 (16bit)
- 目的端口 (16bit)
- 序号 seq (32bit):本报文段第一个数据字节编号
- 确认号 ack (32bit):期望收到下一个字节序号,确认号 = N 代表 N-1 及之前全部收到
- 数据偏移 (4bit):TCP 头部长度,单位 4 字节,决定头部最小 20 字节最大 60 字节
- 保留位 (6bit) +6 个控制标志位 (6bit)
- URG:紧急指针有效,紧急数据优先传
- ACK:确认位,除第一次握手外,后续报文 ACK 基本都置 1
- PSH:推送,接收方收到后立即交给应用层,不要缓存
- RST:重置连接,断开异常连接
- SYN:同步,建立连接握手
- FIN:结束,释放连接
- 窗口大小 (16bit):流量控制,接收方当前剩余缓冲区大小
- 校验和 (16bit):校验 TCP 头 + 数据 + 伪首部
- 紧急指针 (16bit):URG 有效时,指向紧急数据末尾偏移
- 选项(最多 40 字节,如 MSS、窗口扩大、时间戳、SACK)
TIME_WAIT 作用?为什么等待 2MSL?
- 保证最后一个 ACK 报文可以到达对方;如果丢失,对方重发 FIN,我方可以再次回复 ACK
- 等待足够时间,让网络中本次连接残留报文全部消失,防止旧报文干扰新连接。
系统中大量连接存在 CLOSE_WAIT 大量是什么原因
CLOSE_WAIT 是被动关闭方状态:收到客户端 FIN,回复 ACK,等待应用调用 close
大量 CLOSE_WAIT:应用代码忘记关闭 socket,内核收到 FIN,但应用层不调用 close,一直卡在 CLOSE_WAIT
TCP 流量控制是什么?如何实现?
流量控制:防止发送方发送太快,把接收方缓冲区撑爆。
机制:滑动窗口。接收方在 ACK 报文中携带窗口大小,告诉发送方自己还能接收多少字节;发送方发送不能超过窗口。窗口大小由接收缓冲区剩余容量决定。
拥塞控制是什么?和流量控制区别?
拥塞控制:防止网络链路中间路由器被大量数据包淹没,不是接收方缓冲区问题。
四个阶段:
- 慢启动:cwnd 指数增长,直到到达慢启动阈值 ssthresh
- 拥塞避免:cwnd 线性增长
- 快重传:收到 3 个冗余 ACK,立刻重传丢失段,不等待超时
- 快恢复:3 个冗余 ACK,ssthresh 减半,cwnd=ssthresh,进入拥塞避免
TCP 如何保证可靠传输
- 序号 + 确认应答 ACK
- 超时重传:报文丢失或 ACK 丢失,超时后重传
- 滑动窗口流量控制
- 拥塞控制
- 校验和校验数据完整性
- SACK(选择性确认,选项):只重传丢失段,不用重传全部
什么是粘包?
两个独立应用数据,在 TCP 缓冲区被合并成一段读到;或者一个大数据被拆成两段读取
TCP 为什么会粘包
TCP 是字节流,无报文边界,Nagle 算法会合并小数据包
如何解决 TCP 粘包
- 固定长度报文
- 分隔符(如换行符)
- 报文头部携带数据长度(最常用)
UDP 会粘包吗?
UDP不会粘包,只会丢包:UDP 面向报文,一次读一个完整报文
HTTP1.0 / 1.1 区别
1.0:短连接,一次请求一次 TCP,请求完断开;不支持长连接
1.1:
- 长连接 Keep-Alive:一个 TCP 连接可以连续多次请求,默认开启;
- 管线化(pipeline):同一连接连续发送多个请求,不用等前一个响应返回;但是响应必须按请求顺序返回,带来队头阻塞;
- 缓存字段:
Cache-Control,If-Modified-Since; - 断点续传:
Range请求头;
HTTP1.1 的队头阻塞是什么
HTTP1.1 的管线化:在同一个 TCP 连接,连续发多个请求。服务端必须按请求顺序返回响应。
如果第一个请求响应很慢 / 丢包,后面所有请求都被卡住,这就是应用层队头阻塞。
HTTP 缓存机制
强缓存(浏览器不用访问服务器,直接读本地缓存)
Cache-Control: max-age=N:N 秒有效期,优先级更高Expires:绝对过期时间
协商缓存(要发请求给服务器校验,资源没变化返回 304)
Last-Modified+If-Modified-Since:文件最后修改时间ETag+If-None-Match:资源内容哈希指纹,优先级高于 Last-Modified
HTTP/2 相比 HTTP1.1 做了哪些优化
- 二进制帧:不再是文本协议,拆成二进制帧,解析更快;
- 多路复用:一条 TCP 连接上,多个 stream 并行传输,请求响应可以乱序收发,解决 HTTP1.1 应用层队头阻塞;
- 头部压缩 HPACK:静态表 + 动态表 + 固定哈夫曼编码,大幅减少 Header 体积;
- 服务器推送 server push:服务端主动推送资源给客户端(现在浏览器很少用);
- 头部优先级:可以标记 stream 优先级,优先传输重要资源
HTTP2 多路复用,为什么还会有队头阻塞
HTTP2 多路复用解决的是HTTP 应用层队头阻塞(HTTP1.1 管线化的顺序响应问题)。但是 HTTP2 基于 TCP,TCP 是有序可靠传输。如果 TCP 某个数据包丢失,TCP 会暂停交付后续所有报文,等待丢包重传。同连接下所有 stream 全部阻塞,这是 TCP 传输层队头阻塞
HTTPS 加密用的是对称还是非对称
握手阶段用非对称加密交换密钥;业务数据传输用对称加密
HTTPS 怎么防御中间人
HTTPS 中间人如果想解密,必须伪造证书,但是伪造证书没有可信 CA 签名,浏览器校验证书失败,直接报错,阻止访问。
数字证书里面存私钥吗
不存!证书只存网站公钥。私钥保存在服务器,绝对不能泄露
HTTPS 一定安全吗
不是绝对安全:
- 证书过期、证书泄露、CA 被攻破
- 服务器私钥泄露,历史流量如果保存,可被解密(TLS 有前向安全机制 ECDHE 解决)
- 客户端安装恶意根证书
- 弱加密套件
HTTPS 缺点
- TLS 握手增加 RTT,有性能损耗
- 证书需要购买
- CPU 开销:加解密消耗服务器 CPU
DNS 是什么?有什么用?
DNS 是应用层协议,用于将人类可读的域名翻译成计算机识别的 IP 地址
DNS 递归查询和迭代查询的区别,分别发生在哪两者之间
- 递归查询:客户端向本地递归 DNS 发起。客户端只发一次请求,要求 DNS 服务器返回最终结果(IP 或域名不存在),查询的全部工作由本地 DNS 完成。
- 迭代查询:本地 DNS 向根、TLD、权威 DNS 发起。服务器不会帮你继续查询,只返回下一级服务器地址,由本地 DNS 继续发起下一次查询。
DNS 有哪几层缓存
- 浏览器缓存
- 操作系统缓存
- 本地递归 DNS 服务器缓存
- 各级域名服务器缓存
域名无法解析,怎么排查
- 先 ping 域名,看是否返回 IP;
- 用
nslookup/dig测试解析; - 检查本机 hosts 文件;
- 切换公共 DNS(114.114.114.114 / 8.8.8.8),判断是本地 DNS 问题还是域名权威问题;
- dig +trace 追踪完整迭代查询链路,定位在哪一级解析失败;