面试追问地图

主问题必讲关键点下一层追问
OSI/TCP-IP分层职责、封装与解封装一次 HTTP 请求各层发生什么
TCP 三次握手序列号、能力确认、状态迁移报文丢失、SYN Flood、accept 队列
TCP 四次挥手半关闭、TIME_WAIT、2MSL大量 TIME_WAIT/CLOSE_WAIT
TCP 可靠性ACK、重传、滑动窗口、排序RTO、快速重传、流量/拥塞控制
粘包拆包TCP 字节流无消息边界固定长度、分隔符、长度字段
HTTP/1.1/2/3连接复用、帧、多路复用队头阻塞、QUIC 为什么基于 UDP
HTTPS证书、密钥交换、对称加密中间人攻击、会话复用、TLS 1.3 为何 1-RTT、0-RTT 重放
证书链逐级验签、信任锚、域名校验中间 CA 意义、吊销机制、mTLS 与抓包原理
服务端推送长轮询/SSE/WebSocket 对比网关缓冲与超时的坑、百万连接架构、LLM 为何用 SSE
DNS递归/迭代、缓存、记录类型UDP/TCP、缓存污染、负载均衡
Cookie/Session/JWT状态位置和传递方式XSS、CSRF、撤销和集群部署
网络排障DNS、连接、TLS、代理、应用ping 通/不通与 HTTP 是否可用
HTTP 协议基础状态码、GET/POST、keep-alive幂等性、缓存控制、RESTful 规范
网络安全攻击XSS、CSRF、SQL 注入、DDoS防护手段、HTTPS 必要性
HTTP 缓存强缓存、协商缓存、Cache-ControlETag vs Last-Modified、no-cache vs no-store
WebSocketUpgrade 握手、帧格式、全双工心跳机制、与 HTTP 长连接的区别
IP/MAC/ARP逻辑地址 vs 物理地址、ARP 广播ARP 欺骗、为什么需要两套地址
NAT地址转换表、端口映射NAT 穿透、STUN/TURN
CDN边缘节点、DNS 调度、回源缓存刷新、预热、与浏览器缓存的关系

网络题应能画状态迁移或报文顺序,并回答任意一个报文丢失后双方会发生什么。


一、计算机网络

OSI 七层模型和 TCP/IP 四层模型

OSI 七层TCP/IP 四层职责
应用层应用层给应用程序提供接口(HTTP、DNS、FTP)
表示层数据格式转换
会话层建立、管理、终止通信会话
传输层传输层端到端数据传输(TCP、UDP)
网络层网络层路由、转发、分片(IP)
数据链路层网络接口层封帧、差错检测、MAC 寻址
物理层物理介质传输比特流

TCP 和 UDP 区别

  • 连接 :TCP 面向连接(三次握手),UDP 无连接
  • 可靠性 :TCP 可靠传输(序列号、确认应答、超时重传),UDP 不可靠
  • 流量/拥塞控制 :TCP 有,UDP 无
  • 服务对象 :TCP 一对一,UDP 支持一对一/一对多/多对多
  • 首部开销 :TCP 20 字节起,UDP 固定 8 字节
  • 传输方式 :TCP 流式无边界,UDP 有边界

TCP 三次握手

  1. 客户端发送 SYN(seq=client_isn),进入 SYN-SENT
  2. 服务端回复 SYN+ACK(seq=server_isn, ack=client_isn+1),进入 SYN-RCVD
  3. 客户端回复 ACK(ack=server_isn+1),双方进入 ESTABLISHED

为什么是三次不是两次

  • 防止历史重复连接造成混乱(主要原因)
  • 同步双方初始序列号
  • 避免资源浪费

第三次握手丢失 :服务端未收到 ACK 会触发超时重传 SYN-ACK,直到最大重传次数后断开。ACK 本身不重传,由对方重传对应报文。

半连接队列/全连接队列 :收到 SYN 后连接存入半连接队列,三次握手完成后移入全连接队列(accept 队列),等待 accept 取出。

SYN Flood 攻击与半连接队列/全连接队列

频次 ★★★★ · 难度 🟡 · 高频:阿里/字节/美团

队列机制:

客户端 SYN → 半连接队列(syn backlog,未完成握手) → 握手完成 → 全连接队列(accept backlog,等待应用层 accept)
队列存储内容状态大小控制溢出影响
半连接队列(SYN Queue)收到 SYN 但未完成握手的连接SYN-RCVDnet.ipv4.tcp_max_syn_backlog(默认 128~1024)服务端丢弃新 SYN,客户端收不到 SYN-ACK
全连接队列(Accept Queue)完成三次握手待应用 accept 的连接ESTABLISHEDmin(backlog, somaxconn)backloglisten(fd, backlog) 指定,net.core.somaxconn 上限服务端发送 RST 或保留连接(取决于 tcp_abort_on_overflow

面试追问:

  • SYN Flood 攻击原理?→ 攻击者发送大量 SYN 但不回复 ACK,填满服务端半连接队列,导致正常客户端的 SYN 被丢弃。本质是资源不对称攻击——攻击者消耗极少的本地资源就能耗尽服务端内存和队列。
  • 如何防御 SYN Flood?
    • SYN Cookie(最常用):不分配半连接结构体,将连接信息编码到 SYN-ACK 的 seq(seq = hash(src_ip, src_port, dst_ip, dst_port, secret)),客户端回复 ACK 时服务端解码验证,通过才分配连接——将 O(内存) 变为 O(计算),是 SYN Flood 的”银弹”
    • tcp_syncookies = 1:内核在检测到半连接队列满时自动启用,Linux 默认开启
    • 缩短 SYN-ACK 重传次数tcp_synack_retries 从默认 5 降到 2),加速清理僵尸半连接
    • 增大半连接队列tcp_max_syn_backlog
    • 反向代理/防火墙在边缘层拦截攻击流量,不让攻击包打到业务服务器
  • 全连接队列满的表现?→ ss -lnt 查看 Send-Q(当前 backlog),若 Recv-Q > 0 表示队列有积压;netstat -s | grep overflowed 查看溢出计数。应用层应尽快 accept 或使用非阻塞模型(如 Netty 的 eventloop 异步处理)。
  • tcp_abort_on_overflow 的作用?→ 设置为 0(默认),全连接队列满时内核丢弃 ACK 并重发 SYN-ACK(客户端重传 ACK 时可能 enter);设置为 1,直接发 RST 断开(客户端收到 connection reset by peer)。生产环境推荐保持 0。

TCP 四次挥手

  1. 主动方发送 FIN,进入 FIN-WAIT-1
  2. 被动方回复 ACK,进入 CLOSE-WAIT(此时被动方可能还有数据要发送)
  3. 被动方发完数据后发送 FIN,进入 LAST-ACK
  4. 主动方回复 ACK,进入 TIME-WAIT,等待 2MSL 后关闭

为什么不能合并中间两次 :被动方收到 FIN 时,应用层可能还有数据要发送,所以 ACK 和 FIN 通常分开发送。但如果被动方没有数据要发送且开启了延迟确认,第二、三次可以合并。

为什么等待 2MSL :确保最后一个 ACK 能到达被动方;让网络中残留的数据包消亡。

TCP 重传机制

机制触发条件特点
超时重传RTO 内没收到 ACKRTO 基于 RTT 动态计算(加权平均 + 波动量);每次重传 RTO 翻倍(指数退避)
快速重传收到 3 个重复 ACK不等 RTO 直接重传,解决”超时太久”的问题
SACK选择性确认(TCP 选项)ACK 里带上已收到的不连续块,只重传真正丢的段
D-SACK重复 SACK告诉发送方”这段我收到过两次”,用于区分是包丢了还是 ACK 丢了

常见追问:快速重传解决了超时时间的问题,但发送方不知道该重传一个还是全部 → SACK 补上这块信息。

TCP 流量控制 vs 拥塞控制

  • 流量控制(滑动窗口):控制的是接收方的处理能力。接收方在 ACK 里通告接收窗口(rwnd = 接收缓冲区剩余空间),发送方未确认的数据量不能超过 rwnd。窗口为 0 时发送方停发,靠零窗口探测报文避免死等。
  • 拥塞控制(cwnd):控制的是网络的承载能力,防止把网络打垮(见下节)。
  • 发送窗口 = min(rwnd, cwnd)——两个约束同时生效,一个保护对端,一个保护网络。

通用概念:接收窗口是最典型的背压:把下游的真实状况逆着数据流传回上游;而拥塞控制面向的是网络而非对端。

TCP keepalive vs HTTP keep-alive

TCP keepaliveHTTP keep-alive
层级传输层,内核实现应用层,HTTP 头
作用探测死连接(默认 2 小时无数据才开始探测)连接复用,一个 TCP 连接发多个请求
打开方式SO_KEEPALIVE 套接字选项HTTP/1.1 默认开启,Connection: close 关闭

常见追问:长连接推送服务为什么还要应用层心跳?→ TCP keepalive 周期太长且中间设备(NAT/LB)可能提前掐断空闲连接,应用层心跳(如每 30s)既保活又能探测应用假死。

TCP 拥塞控制

四个阶段:

  • 慢启动 :cwnd 从 1 开始,每收到一个 ACK 就 +1,指数增长。当 cwnd >= ssthresh 时进入拥塞避免
  • 拥塞避免 :每收到一个 ACK,cwnd += 1/cwnd,线性增长
  • 拥塞发生(超时重传) :ssthresh = cwnd/2,cwnd 重置为 1,重新慢启动
  • 快速恢复(快速重传) :收到 3 个重复 ACK 时,cwnd = cwnd/2,ssthresh = cwnd,进入快速恢复而非慢启动

TCP 粘包/拆包如何解决?

是什么:TCP 是字节流协议,没有消息边界——发送方连续两次 send 可能被接收方一次 read 收全(粘包),也可能一次 send 被拆成多次 read(拆包)。应用层必须自己划定消息边界,常见三种方式:

  • 固定长度消息
  • 特殊字符边界(如早期文本协议用 \r\n 分隔)
  • 自定义消息结构(包头固定长度 + 数据长度字段),Netty 对应 LengthFieldBasedFrameDecoder,见Netty与RPC”编解码与 TCP 边界”

HTTP 是怎么解决的:HTTP/1.1 靠 Content-Length 头字段显式告知 body 长度(不知道长度时用 Transfer-Encoding: chunked 分块,每块自带长度前缀);HTTP/2 把消息拆成自带长度字段的二进制帧(Frame),边界问题在协议层面天然消失,不再需要应用层额外处理。

HTTP 常用状态码

  • 2xx :200 成功
  • 3xx :301 永久重定向,302 临时重定向
  • 4xx :404 资源不存在,405 方法不支持
  • 5xx :500 服务器内部错误,502 网关收到无效响应,504 网关超时

GET 和 POST 区别

  • 语义 :GET 是安全且幂等的(只读),POST 会修改资源
  • 参数位置 :GET 在 URL 中(仅 ASCII,浏览器限制长度),POST 在 body 中(任意格式,无限制)
  • 缓存 :GET 可缓存,POST 一般不缓存

HTTP 和 HTTPS 区别

  • HTTPS 在 TCP 和 HTTP 之间加入 SSL/TLS 加密
  • HTTP 默认端口 80,HTTPS 默认 443
  • HTTPS 需要 CA 证书
  • HTTP 明文有窃听、篡改、冒充风险;HTTPS 解决这些问题

HTTPS 握手过程(TLS 1.2)

  1. ClientHello:客户端发送协议版本、随机数、密码套件列表
  2. ServerHello:服务端确认版本、随机数、密码套件、返回数字证书
  3. 客户端验证证书,用公钥加密 pre-master key 发给服务端
  4. 双方用三个随机数计算会话秘钥,互相通知加密算法切换

注意上述是 RSA 密钥交换流程,完整握手需要 2-RTT;TLS 1.2 用 ECDHE 也仍需 2-RTT(多一次往返协商 DH 参数)。TLS 1.3 如何压到 1-RTT 见下节。

TLS 1.3 握手:为什么只要 1-RTT?

是什么:TLS 1.3(RFC 8446,2018)把握手从 2-RTT 压缩到 1-RTT,核心一招:客户端不等协商结果,在 ClientHello 里直接带上 DH 公钥(key_share 扩展,赌服务端支持主流曲线如 x25519),服务端在 ServerHello 里回自己的 DH 公钥——一个往返双方就算出了会话密钥。

TLS 1.2 (ECDHE)                     TLS 1.3
C → S: ClientHello                  C → S: ClientHello + key_share ★
C ← S: ServerHello, Certificate,    C ← S: ServerHello + key_share,
       ServerKeyExchange                   {Certificate, Finished}(已加密)
C → S: ClientKeyExchange, Finished  C → S: {Finished}, 直接发应用数据 ★
C ← S: Finished
------ 2-RTT 后才能发数据 ------      ------ 1-RTT 后即可发数据 ------

为什么能砍掉一个 RTT(三个配套设计,答题按这个顺序说):

  1. 砍掉 RSA 密钥交换:只保留 (EC)DHE,强制前向安全(服务端私钥泄露也解不开历史流量;RSA 交换模式下私钥一漏全部历史密文可解)
  2. 密码套件从 300+ 精简到 5 个:没有协商空间,客户端”猜中”概率极高;猜错服务端回 HelloRetryRequest 退化为 2-RTT
  3. 证书也加密传输:ServerHello 之后的所有握手消息都用刚算出的密钥加密,中间人连服务端证书都看不到(TLS 1.2 证书是明文)

0-RTT(会话恢复):曾经连接过的客户端持有服务端发的 PSK(session ticket),重连时 ClientHello 里直接附带早期数据(early data)——第 0 个 RTT 就把 HTTP 请求发出去了。代价是重放攻击风险:攻击者截获 0-RTT 报文原样重发,服务端无法区分,所以 0-RTT 数据只能承载幂等请求(GET),网关(如 Nginx ssl_early_data)默认关闭。

与 QUIC 的衔接:QUIC(HTTP/3 底层)把 TLS 1.3 直接内建进传输层,传输握手和加密握手合并在同一个 1-RTT 里完成(TCP+TLS1.3 = 1 RTT 建 TCP + 1 RTT 握 TLS = 2-RTT,QUIC 只要 1-RTT,会话恢复时 0-RTT)——这是”QUIC 建连快”的真正来源,见下文 HTTP/2 与队头阻塞相关小节。

常见追问

  • TLS 1.3 还需要证书吗?→ 需要。DH 交换只保证密钥安全,不证明”对端是谁”,身份认证仍靠证书签名(防中间人)
  • 0-RTT 为什么防不了重放?→ early data 用的是上次会话的 PSK 派生密钥,服务端处理它时握手尚未完成,没有本次的新鲜随机数参与,无法识别”这是不是重发的旧报文”
  • 会话复用 TLS 1.2 和 1.3 有什么区别?→ 1.2 用 session ID(服务端存状态)或 session ticket;1.3 统一为基于 PSK 的 ticket 机制,且每次恢复会重新做 DH(保持前向安全)

证书链怎么验证?中间人为什么伪造不出有效证书?

频次 ★★★ · 难度 🟡

是什么:握手中服务端返回的不是一张证书而是证书链:站点证书(leaf)← 中间 CA 证书 ← 根 CA。每张证书 = 明文部分(域名 SAN、公钥、有效期、签发者)+ 签发者用自己私钥对明文摘要做的签名。根 CA 证书预装在操作系统/浏览器的信任库里,是自签名的信任锚

逐级验签流程

1. 取站点证书,按"签发者"字段找到中间 CA 证书
2. 用中间 CA 的公钥解开站点证书上的签名得到摘要,
   与自己对证书明文重新计算的摘要比对 —— 一致则此级可信
3. 同法用根 CA 公钥验中间 CA 证书
4. 根 CA 是否在本地信任库中?在 → 信任链闭合
5. 附加检查:域名匹配(SAN)、有效期、吊销状态(CRL/OCSP)

为什么中间人拿不到有效证书(答题核心,逐条堵死它的路):

  • 原样转发真证书?→ 证书里公钥对应的私钥在真服务器手里,中间人解不开后续密钥交换,链路建不起来
  • 自己伪造一张?→ 签名需要某个受信 CA 的私钥,拿不到;用自己私钥签,第 4 步找不到信任锚直接断链
  • 骗 CA 给它签目标域名的证书?→ CA 签发前要做域名所有权校验(DNS 记录/文件验证);CA 违规乱签会被**证书透明度日志(CT)**公开曝光、被浏览器整体除名(DigiNotar 因此破产)

所以 Charles/Fiddler 抓 HTTPS 包必须先让你手动安装它的根证书——本质是自愿把中间人加进信任锚;App 侧对抗手段是证书锁定(certificate pinning),把预期证书/公钥硬编码进客户端,不认系统信任库里的其他链。

自签名与 mTLS 场景

场景做法信任来源
公网网站公共 CA(Let’s Encrypt/DigiCert)系统内置信任库
企业内网自建根 CA 签发运维把根证书推送到所有机器信任库
服务间双向 TLS(mTLS)客户端也出示证书,双方互验服务网格(Istio)自动签发并轮换短期证书

普通 TLS 只验服务端身份;mTLS 让服务端也要求并校验客户端证书,微服务零信任架构里用它替代”IP 白名单”做服务间身份认证。

常见追问

  • 为什么要有中间 CA,根 CA 直接签不行吗?→ 根私钥太贵重,泄露 = 整个信任体系崩塌,所以离线冷存;中间 CA 承担日常签发,出事可单独吊销,不动摇根
  • 证书被吊销了客户端怎么知道?→ CRL(全量吊销列表,大而更新慢)→ OCSP(在线实时查,有隐私和可用性问题)→ OCSP Stapling(服务端代查,把带 CA 签名的结果钉进握手,主流方案)
  • 证书校验和加密是什么关系?→ 独立的两件事:DH/RSA 解决”密钥不被窃听”,证书解决”对端是谁”——只加密不验身份,加密通道可能直通中间人(呼应上一节 TLS 1.3 追问)

通用概念:证书链是信任的逐级传递——用”已信任者的签名”把信任从锚点延伸到陌生实体,验证方只需预置极少量的锚。同类:JWT 签名验证(服务端只信自己的签名密钥,见安全认证)、软件包签名(Maven/APT 的 GPG 校验,见构建与依赖管理)。

HTTP/1.1 和 HTTP/2.0 区别

  • 头部压缩 :HPACK 算法,消除重复头部
  • 二进制格式 :统称为帧(Headers Frame + Data Frame)
  • 并发传输 :多 Stream 复用一条 TCP 连接,解决队头阻塞
  • 服务器推送 :服务端主动推送资源(现代浏览器已逐步弃用)

HTTP/3(QUIC)解决了什么问题?

频次 ★★★ · 难度 🟡 · 高频:字节/腾讯

HTTP/3 的最大变化:将传输层从 TCP 更换为 QUIC(基于 UDP)

问题HTTP/2 的痛点HTTP/3(QUIC)的解法
队头阻塞TCP 丢包阻塞整条连接(TCP 必须按序交付),即使只丢一个包,后面的 HTTP/2 Stream 都得等重传QUIC 在 UDP 上自建多路复用,丢包只影响单个 Stream,其他 Stream 不受影响
连接建立延迟TCP 三次握手(1-RTT)+ TLS 1.3 握手(1-RTT)→ 至少 2-RTT 才能发数据QUIC 支持 0-RTT(首次 1-RTT,后续可 0-RTT 发数据),握手 + 数据传输合并
连接迁移TCP 连接靠四元组(src_ip:port, dst_ip:port)标识,切换网络(WiFi → 4G)IP 变 → 连接重建QUIC 用 Connection ID 标识连接,IP/端口变化连接不中断,移动场景无需重连
拥塞控制依赖内核 TCP 栈,升级需要修改 OS 参数QUIC 在用户态实现拥塞控制,可快速迭代(如 BBR、Cubic 切换),不像 TCP 绑定内核版本

QUIC 的核心设计:

  • 基于 UDP,在用户态实现可靠传输(自建 ACK/重传/流控),避免内核升级依赖
  • 内置 TLS 1.3,加密默认强制(不像 TCP 可选),头部和载荷全部加密
  • 单连接内多个 Stream 独立有序,一个 Stream 丢包不影响其他 Stream

面试追问:

  • QUIC 的 0-RTT 不安全吗?→ 0-RTT 存在重放攻击风险——攻击者截获 0-RTT 请求重复发送,服务端无法区分。QUIC 禁止在 0-RTT 中发送幂等操作,或通过时间窗口限制。
  • QUIC 当前部署情况?→ 谷歌全系产品(Chrome/Youtube/搜索)使用 QUIC 超过十年;Cloudflare、Facebook 广泛部署;国内字节跳动大规模使用。HTTP/3 标准已发布(RFC 9114),主流浏览器和服务端(nginx、Caddy、Envoy)均已支持。

服务端怎么把消息推给浏览器?长轮询、SSE、WebSocket 怎么选?

频次 ★★★ · 难度 🟡

是什么:HTTP 是请求-响应模型,服务端不能主动开口,“推送”都是绕出来的:

维度短轮询长轮询SSEWebSocket
原理定时重复请求请求挂起,有数据才响应,响应完立刻再发下一个一次请求,响应不结束,流式吐事件HTTP 101 Upgrade 后升级为全双工
方向伪推(拉的变体)服务端 → 客户端单向双向
协议HTTPHTTPHTTP(text/event-stream独立 ws:// 协议
实时性差(取决于间隔)最好
断线续传无所谓天然协议内建:自动重连 + Last-Event-ID手动实现心跳/重连/补偿
服务端成本大量无效请求挂起连接一个长连接一个长连接 + 帧协议处理

SSE 长什么样:响应头 Content-Type: text/event-stream,服务端往同一个响应里持续写:

id: 42
event: tick
data: {"price": 100.5}
 
data: 第二条消息

浏览器 EventSource API 自动解析事件、断线后自动带 Last-Event-ID 头重连——续传是协议内建的,这是它相对 WebSocket 的最大优势。ChatGPT 式打字机输出就是 SSE,它已是 LLM 流式响应的事实标准。

怎么选(先问方向,再问频率):

  • 只要服务端→客户端:通知、行情、AI 流式输出、任务进度 → SSE,完整保留 HTTP 语义(标准认证头、经过网关/CDN 不用特殊处理)
  • 双向高频交互:IM、协同编辑、多人游戏 → WebSocket
  • 低频或兼容性兜底 → 长轮询,任何网络环境都能过

与网关/LB 配合的坑(区分背题和实战的部分):

  • 代理缓冲:Nginx 默认 proxy_buffering on 会攒够缓冲区才转发,SSE 一条都吐不出来——要 proxy_buffering off 或响应头 X-Accel-Buffering: no
  • 空闲超时:LB/网关的 idle timeout(常见 60s)会掐掉没有流量的长连接——SSE 定期发注释行 : keepalive,WebSocket 用 ping/pong 帧保活
  • 有状态连接:长连接绑定具体节点,网关扩缩容/发布会掐断全部连接,要预估重连风暴(指数退避 + 抖动);WebSocket 过代理还需转发 Upgrade/Connection
  • 连接数上限:HTTP/1.1 下 SSE 独占一个连接,浏览器同域名 6 连接封顶,多标签页会耗尽——HTTP/2 多路复用解决(见上一节)

常见追问

  • 百万在线的推送系统怎么架构?→ 接入层(Netty 长连接网关)只管连接,业务层无状态;推送消息经 MQ 广播到网关节点,各节点查本地连接表下发——连接与业务解耦,见Netty与RPC
  • SSE 能传二进制吗?→ 不能,只支持 UTF-8 文本;二进制场景用 WebSocket 或退化为 base64
  • 为什么 LLM 接口用 SSE 而不是 WebSocket?→ 纯单向流,SSE 够用且成本低:认证沿用 HTTP header、网关/LB 不需要特殊改造、断线续传内建;WebSocket 的双向能力用不上,还得自建心跳重连

通用概念:推 vs 拉的取舍贯穿系统设计——推实时但要管背压,拉自控速但有延迟:Kafka 消费端选拉(见消息队列”Kafka 是推模式还是拉模式”)、Feed 流推拉结合(见系统设计)。

DNS 解析流程

客户端 -> 本地 DNS -> 根 DNS -> 顶级域 DNS -> 权威 DNS -> 返回 IP

DNS 使用 UDP 还是 TCP :都用,端口 53。查询一般用 UDP(低延迟),区域传送或响应超过 512 字节时用 TCP。

  • 存储位置 :Cookie 在客户端,Session 在服务端
  • 安全性 :Cookie 易受 XSS 攻击(可设置 HttpOnly 防护),Session 更安全但需防范 Session 劫持
  • 容量 :Cookie 约 4KB,Session 理论上无限制

分布式场景的会话方案(Session 集群、JWT、SSO)详见安全认证

Socket、TCP、HTTP 关系

  • HTTP:应用层协议,定义数据格式
  • TCP:传输层协议,建立可靠连接
  • Socket:通信的端点抽象,提供网络编程接口

打开网页的完整网络过程

  1. URL 解析 -> 2. 缓存判断(浏览器/系统/路由器/ISP DNS)-> 3. DNS 解析 -> 4. ARP 获取 MAC -> 5. TCP 三次握手 -> 6. TLS 握手(HTTPS)-> 7. 发送 HTTP 请求 -> 8. 服务器处理并返回

常见网络攻击

  • DDoS :分布式拒绝服务攻击,通过大量请求淹没服务器
  • SQL 注入 :用户输入未经转义直接拼入 SQL,用参数化查询解决
  • CSRF :跨站请求伪造,用 Token 验证、验证 Referer 解决
  • XSS :跨站脚本攻击,输入验证、输出编码、CSP 策略解决
  • DNS 劫持 :篡改 DNS 响应,使用 DNS over HTTPS/TLS 解决

XSS/CSRF 的攻击方式与防护细节、密码存储与认证体系详见安全认证


二、HTTP 深入

HTTP 请求报文和响应报文是怎样的?

是什么:HTTP 报文 = 起始行 + 头部 + 空行 + 消息体(可选)。

请求报文

GET /api/users?page=1 HTTP/1.1          ← 请求行(方法 URI 协议版本)
Host: example.com                        ← 请求头
Accept: application/json
User-Agent: Mozilla/5.0
                                         ← 空行(CRLF,头与体之间的分隔)
{"key":"value"}                          ← 消息体(POST/PUT 才有)

响应报文

HTTP/1.1 200 OK                          ← 状态行(协议版本 状态码 原因短语)
Content-Type: application/json           ← 响应头
Content-Length: 123
Set-Cookie: session=abc123
                                         ← 空行
{"data": [...]}                          ← 消息体

常见追问:请求头和响应头有什么区别?→ 请求头主要传客户端信息(Accept、User-Agent、Authorization)、请求条件(If-Modified-Since);响应头传服务器信息(Set-Cookie、Content-Type)、缓存指令(Cache-Control、ETag)。

什么是强缓存和协商缓存?它们的工作原理是什么?

频次 ★★★★ · 难度 🟡 · 高频:字节/美团

是什么:浏览器缓存的两级策略——强缓存直接复用以避免发请求,协商缓存发请求但让服务端判断是否可复用,节省传输。

强缓存(不发请求,状态码 200 OK from disk/memory cache):

  • Cache-Control: max-age=3600(HTTP/1.1,相对时间,优先级最高)
  • Expires: Thu, 01 Dec 2025 16:00:00 GMT(HTTP/1.0,绝对时间,服务器时钟不准会出错)

协商缓存(发请求,服务端返回 304 Not Modified 表示”用你的缓存”):

  • ETag / If-None-Match:服务端生成资源内容的唯一标识(哈希/版本号),客户端下次请求带上,一致则返回 304
  • Last-Modified / If-Modified-Since:服务端返回资源最后修改时间,客户端下次请求带上,未修改则返回 304

强缓存 vs 协商缓存决策流程

浏览器请求资源
  ├── 有缓存 && 强缓存未过期 → 直接用缓存(不发请求)
  ├── 强缓存过期 → 发请求,带 If-None-Match / If-Modified-Since
  │   ├── 304 → 用本地缓存(刷新过期时间)
  │   └── 200 → 下载新资源,更新缓存
  └── 无缓存 → 发请求,下载资源并缓存

常见追问

  • ETag 和 Last-Modified 哪个优先级高?→ ETag 更高。ETag 能解决”1 秒内修改两次 Last-Modified 无法感知”的问题,以及”文件内容不变但 mtime 变了”的误判。
  • Cache-Control: no-cacheno-store 的区别?→ no-cache 不是”不缓存”,而是每次用缓存前必须找服务端验证(走协商缓存);no-store 才是真正的”完全不缓存,每次重新下载”。
  • 前端资源怎么设置缓存策略?→ HTML 文件设协商缓存(no-cache),JS/CSS/图片等带 hash 文件名设强缓存 + 超长 max-age(max-age=31536000),内容变了文件名就变,天然失效。

HTTP 头部字段有哪些常见类型?各自作用是什么?

通用头部Cache-Control(缓存策略)、Connection(连接管理)、Transfer-Encoding(传输编码,如 chunked)。

请求头部

  • Host:目标主机(HTTP/1.1 必带,支持虚拟主机)
  • User-Agent:客户端标识
  • Accept / Accept-Encoding / Accept-Language:客户端能处理的格式
  • Authorization:认证信息
  • Referer:来源页面 URL,用于防盗链和统计分析
  • Range: bytes=0-1023:断点续传,只请求文件的一部分
  • If-None-Match / If-Modified-Since:协商缓存

响应头部

  • Content-Type:响应体 MIME 类型(text/htmlapplication/jsonmultipart/form-data
  • Content-Length:响应体字节数
  • Set-Cookie:设置 Cookie
  • ETag / Last-Modified:提供缓存验证信息
  • Location:重定向目标(配合 301/302)
  • Access-Control-Allow-Origin:CORS 跨域白名单

常见追问Content-Type 常见取值有哪些?→ text/htmlapplication/jsonapplication/x-www-form-urlencoded(表单默认)、multipart/form-data(文件上传)、text/event-stream(SSE 流式推送)、application/octet-stream(二进制下载)。

HTTP 管道化是什么?它解决了什么问题?

是什么:HTTP/1.1 管道化允许客户端在一个 TCP 连接上连续发送多个请求而不等上一个响应返回(类似流水线),服务端按请求顺序返回响应。

为什么几乎没人用:队头阻塞(HOL Blocking)——第一个响应慢会把后面所有响应堵住,服务端必须按序返回。浏览器默认关闭管道化,实际用”多个并行 TCP 连接”(同域名 6 个连接)来弥补。HTTP/2 的多路复用从根本上解决了这个问题。

HTTP 多个 TCP 连接怎么实现?

是什么:浏览器对同一域名建立多个 TCP 连接(HTTP/1.1 规范建议 ≤2,实际浏览器默认 6 个),并行发送请求,每个连接的响应独立处理,互不阻塞。域名分片(sharding)可突破此限制——把资源分散到多个域名(static1.example.comstatic2.example.com),每个域名独立享有 6 连接配额。

HTTP/2 的改进:多路复用——一个 TCP 连接上同时跑多个 Stream,每个 Stream 独立传输,彻底消除 HTTP/1.1 的队头阻塞(但 TCP 层面的队头阻塞仍存在,由 HTTP/3 的 QUIC 解决)。


三、网络层与数据链路层

网络分层模型的封装与解封装过程是怎样的?

是什么:数据从应用层往下传,每层加自己的头部(封装);到达目标后从下往上,每层去掉对应头部(解封装):

发送端(封装)                          接收端(解封装)
应用层:  HTTP 数据                      → 应用层拿到 HTTP 数据
传输层:  TCP 头 + HTTP 数据             → 传输层去 TCP 头
网络层:  IP 头 + TCP 头 + HTTP 数据     → 网络层去 IP 头
链路层:  MAC 头 + IP 头 + TCP 头 + HTTP + MAC 尾  → 链路层去 MAC 头尾

常见追问:封装过程中源/目标 IP 和 MAC 如何变化?→ IP 地址端到端不变(除非经过 NAT),MAC 地址每经过一跳路由器就变——源 MAC 变成本跳的出口 MAC,目标 MAC 变成下一跳的入口 MAC。

数据链路层和网络层各有哪些主要协议?

数据链路层

  • ARP:IP 地址 → MAC 地址映射
  • RARP:MAC 地址 → IP 地址(已基本被 DHCP 取代)
  • 以太网(Ethernet):最主流的局域网协议,CSMA/CD 载波监听多路访问

网络层

  • IP:尽力而为的不可靠传输,负责寻址和路由
  • ICMP:控制报文(ping 用的就是 ICMP Echo Request/Reply)
  • IGMP:组播管理
  • 路由协议:OSPF(内部网关)、BGP(外部网关,互联网骨干)

ARP 协议是什么?它在网络通信中有什么作用?

是什么:ARP(Address Resolution Protocol)在局域网内通过 IP 地址查找对应的 MAC 地址。主机发 ARP 广播请求”谁的 IP 是 192.168.1.5?“,目标主机单播回应”是我,我的 MAC 是 aa:bb:cc:dd:ee:ff”。查到的映射缓存到 ARP 表(arp -a 查看)。

ARP 欺骗/中间人攻击:攻击者伪造 ARP 响应,把网关 IP 映射到自己的 MAC,使受害者流量经过攻击者。防御:交换机端口绑定、ARP 防火墙。

IP 地址和 MAC 地址有什么区别?在网络通信中各自扮演什么角色?

维度IP 地址MAC 地址
层级网络层数据链路层
长度IPv4 32 位 / IPv6 128 位48 位(如 aa:bb:cc:dd:ee:ff
作用标识主机在网络中的位置,用于路由标识网卡硬件,用于局域网内寻址
可变性可配置、可变化出厂烧录,唯一(可软件修改)
类比收货地址身份证号

为什么需要两套地址:IP 是逻辑地址,支持网络拓扑和路由聚合;MAC 是物理地址,保证数据在最后一跳(局域网)到达正确的网卡。IP 负责”送到哪个网络”,MAC 负责”送到该网络中的哪台机器”。

NAT(网络地址转换)是什么?有什么作用?

是什么:NAT 让私有 IP 地址的主机通过一个公网 IP 访问互联网。路由器维护映射表,把内网 IP:端口 ↔ 公网 IP:端口 的转换关系记录下来。

作用:缓解 IPv4 地址枯竭(一个公网 IP 供整个家庭/公司上网);隐藏内网拓扑(外部只能看到 NAT 设备的公网 IP)。

NAT 穿透问题:NAT 对”由内向外发起”的连接天然支持,但”由外向内主动连接”会被 NAT 挡掉。P2P 应用(BT、视频通话)需要 NAT 穿透技术(STUN/TURN/ICE)。


四、WebSocket 与实时通信

WebSocket 是什么?它在网络通信中有什么作用?

频次 ★★★ · 难度 🟡

是什么:WebSocket 是基于 TCP 的全双工通信协议,通过 HTTP Upgrade 机制从 HTTP 升级而来。建立后客户端和服务端可以随时互相发送消息,无需每次请求-响应。

建立过程

客户端请求:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
 
服务端响应:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WebSocket 帧格式:头部最小 2 字节(opcode + 掩码位 + 长度),其后是掩码密钥 + 有效载荷。数据帧支持文本和二进制(blob/arraybuffer)。

与 HTTP 对比:HTTP 是请求-响应,客户端不问服务端不能主动发;WebSocket 是全双工,双方随时可发。WebSocket 建连后不再有 HTTP 头的开销,帧头最小仅 2 字节。详见上文”服务端推送选型”的四种方案对比。

常见追问:WebSocket 心跳怎么做?→ 发送 ping 帧(opcode=0x9),对端必须回复 pong 帧(opcode=0xA)。和 TCP keepalive 不同,WebSocket 的 ping/pong 是应用层帧,不依赖内核参数。


五、网络安全补充

TCP 连接建立过程中,SYN 洪泛攻击如何发生?如何防范?

频次 ★★ · 难度 🟡

是什么:攻击者伪造大量不存在的源 IP,向服务端发送 SYN 包。服务端回复 SYN-ACK 后进入 SYN-RCVD 状态,连接加入半连接队列,等待 ACK 到来。但源 IP 是伪造的,ACK 永远不会来——半连接队列被占满,合法用户无法建立新连接。

防范措施

  • SYN Cookie:不立即分配半连接资源,而是用客户端 IP/端口/时间戳等算出一个 cookie 作为 SYN-ACK 的 seq,只有收到合法 ACK(cookie 验证通过)才分配资源
  • 缩短 SYN 超时重传时间:减少半连接占用时间
  • 增大半连接队列tcp_max_syn_backlog 参数
  • 防火墙/负载均衡器限流:CDN/高防 IP 在攻击流量到达源站前清洗

什么是端口扫描?在网络安全中有什么作用?

是什么:端口扫描是逐端口发送探测包,根据响应判断端口是否开放及运行的服务。nmap 是最常用的端口扫描工具。

常见扫描类型:SYN 扫描(半开扫描,不发最后的 ACK,不建立完整连接,隐蔽)、TCP 全连接扫描(完整三次握手,日志会记录)、UDP 扫描(发 UDP 包,ICMP 端口不可达说明关闭)。

常见追问:防御端口扫描的方法?→ 防火墙限制连接频率;只开放必要端口;使用端口敲门(port knocking)隐藏敏感端口。


六、CDN 与内容分发

CDN 是什么?它在网络传输中有什么作用?

频次 ★★★★ · 难度 🟡 · 高频:字节/美团

是什么:CDN(内容分发网络)将静态资源缓存到遍布全球的边缘节点,用户请求就近响应,减少延迟和回源带宽。

工作流程

  1. 用户请求 cdn.example.com/image.jpg
  2. DNS 智能解析返回离用户最近的 CDN 节点 IP(基于 LDNS 出口 IP 判断地理位置)
  3. 边缘节点命中缓存 → 直接返回;缓存未命中 → 回源站拉取 → 缓存 → 返回
  4. 源站内容更新时,通过 CDN 刷新/预热接口主动失效缓存

DNS 调度 vs Anycast 调度:传统 CDN 用 DNS 把用户引导到最近的边缘节点,依赖用户使用的 DNS 服务器(LDNS)的 IP 做地理位置判断;大规模 CDN 则结合 Anycast(同一 IP 在多个节点同时广播,运营商路由自动找最近路径)。

常见追问:CDN 缓存和浏览器缓存的关系?→ 浏览器缓存是最靠近用户的一层,CDN 缓存是中间层,源站是最终数据源。CDN 缓存命中时,响应头里的 Cache-Control 照常传递给浏览器,让浏览器也缓存。两层缓存叠加,进一步减少源站压力。

通用概念:CDN 是”把数据推到离用户最近的地方”——和 DNS 缓存、Redis 缓存、CPU Cache 都遵循相同的”就近原则”,只是层级从芯片→内存→网络→全球逐级放大。