这篇按后端面试的追问顺序整理计算机网络。先扫知识点,再遮住答案做 Q/A/W 自测:A 可以直接拿去回答,W 负责把背后的因果链补上。

一、网络分层与寻址(高频)

知识点

  • OSI 与 TCP/IP:OSI 是七层参考模型;工程中常用 TCP/IP 四层或五层模型。两者用于划分职责,不能把层数差异理解成协议运行了两套网络。
  • 逐层封装:应用数据向下经过传输层、网络层和链路层,依次加入 TCP/UDP 首部、IP 首部和帧首尾;接收端按相反顺序解封装。
  • IP 尽力而为:IP 负责跨网络寻址和转发,不承诺送达、顺序或去重;可靠性需要 TCP 或应用层机制补足。
  • 最长前缀匹配:路由器用目标 IP 查询路由表,优先选择前缀最长的匹配项;没有更具体的路由时才走默认路由。
  • ARP 的边界:ARP 在同一链路内把 IPv4 地址解析为 MAC 地址。目标不在本子网时,主机解析的是下一跳网关的 MAC,而不是远端服务器的 MAC;IPv6 使用邻居发现协议。
  • NAT 映射:家用和企业出口常用源地址转换,把内网地址与端口映射为公网地址与端口;它缓解 IPv4 地址不足,也让入站连接需要端口映射或其他穿透机制。

面试问答

  • Q1:OSI 七层和 TCP/IP 怎么对应?(高频)

A: OSI 是七层参考模型,TCP/IP 实际常按应用、传输、网际和网络接口四层回答。HTTP、DNS 在应用层,TCP、UDP 在传输层,IP 在网际层,以太网和 Wi-Fi 在接口层。别死背层数,重点是每层只依赖相邻层提供的能力。

W: 拿浏览器发 HTTP 请求来说,应用层不用关心 Wi-Fi 怎么重传帧,TCP 也不理解 URL。每层加上自己的控制信息,再交给下一层。这样更换网卡时不用改 HTTP,实现 IPv6 时也不用重写所有应用协议,各层可以沿着自己的边界演进。

  • Q2:访问外网时 ARP 查的是谁?

A: 关键是先用子网掩码判断目标在哪。目标在同一子网,就 ARP 查询目标主机的 MAC;目标在外网,就查默认网关的 MAC,把帧交给网关。IP 包的目标仍是远端服务器,沿途变化的是每一跳使用的链路层地址。

W: 假设电脑要访问公网 IP,广播域里不可能存在那台远端服务器。若直接广播询问它的 MAC,不会有人回答。电脑真正能直接交付帧的只有本地网关,所以先找到网关的 MAC;路由器收到后拆掉链路层首部,再根据目标 IP 选择下一跳并重新封装。


二、DNS 域名解析(高频)

知识点

  • 解析链路:应用先查自身和操作系统缓存,再询问递归解析器;递归解析器在未命中缓存时,从根、顶级域和权威 DNS 逐级获得结果。
  • 递归与迭代:客户端通常向递归解析器要最终答案;根和顶级域服务器通常返回下一步应询问的权威服务器地址,由解析器继续查询。
  • 常见记录:A 指向 IPv4,AAAA 指向 IPv6,CNAME 指向另一个域名,MX 指定邮件服务器,TXT 保存文本验证或策略信息。
  • 缓存与 TTL:解析结果按记录的 TTL 缓存。TTL 小,变更传播更快但查询压力更高;TTL 大,缓存命中率更高但切换生效更慢。
  • UDP 与 TCP:传统 DNS 查询多使用 UDP 53 端口;响应被截断、区域传送等场景会使用 TCP。RFC 7766 要求通用 DNS 实现同时支持 UDP 和 TCP。

面试问答

  • Q1:浏览器怎么把域名解析成 IP?(高频)

A: 先查浏览器、操作系统和本地 hosts,再把请求交给递归 DNS。缓存没命中,递归 DNS 才依次询问根、顶级域和权威服务器,拿到 A 或 AAAA 记录后按 TTL 缓存。逐级查询通常由递归解析器完成,不是浏览器自己一路问下去。

W: 以 api.example.com 为例,根服务器不会保存最终 IP,只会告诉解析器去哪里找 .com;顶级域服务器再指向 example.com 的权威服务器,最终由权威服务器给出记录。层级委派让全球域名不必塞进一台服务器,缓存又避免每次访问都从根开始。


三、TCP 建连与断连(大厂高频)

知识点

  • 连接标识:一条 TCP 连接通常由源 IP、源端口、目标 IP、目标端口四元组标识;同一服务端端口可以同时承载大量不同客户端连接。
  • 三次握手:客户端发送 SYN 和初始序列号,服务端回复 SYN+ACK 及自己的初始序列号,客户端再回 ACK。双方由此确认双向收发能力并同步序列号。
  • 握手防旧连接:RFC 9293 给出的主要理由是防止旧的重复连接请求造成混淆。第三次确认让服务端知道客户端确实接受了本次连接参数。
  • 半连接与全连接队列:Linux 收到 SYN 后把连接放入半连接队列,完成握手后移入等待应用 accept() 的队列;队列溢出、应用接收太慢都会导致建连异常。
  • 四次挥手:TCP 是全双工协议,一端发送 FIN 只表示自己不再发送数据;另一方向可能仍有数据,因此两个方向要分别关闭和确认。
  • 异常状态:主动关闭方通常进入 TIME_WAIT 并等待 2MSL;大量 CLOSE_WAIT 通常说明对端已关闭,但本地应用没有及时调用 close()。

面试问答

  • Q1:TCP 为什么是三次握手?(追问率极高)

A: 三次握手要同步双方的初始序列号,也要确认双向收发能力。只握手两次,服务端不知道自己的 SYN 是否被客户端接受,旧 SYN 还可能触发误建连接。第三个 ACK 把客户端对本次序列号的确认带回来,双方才能进入一致的连接状态。

W: 想象一个旧 SYN 在网络里滞留,原连接早已结束。它后来到达服务端,服务端若两次握手后就认定连接成立,会分配资源等待一条客户端根本不存在的连接。三次握手下,原客户端不会确认服务端的新序列号,服务端就不会把这次旧请求当成正常会话。

  • Q2:两种 WAIT 状态怎么排查?(高频)

A: 这两个状态要分开看。TIME_WAIT 多在主动关闭方,2MSL 用来应对 FIN 重传并淘汰旧报文,数量高先查短连接。CLOSE_WAIT 说明对端已经关闭,本地代码却没调用 close(),重点查连接泄漏、异常分支和阻塞调用。

W: 如果最后一个 ACK 丢了,被动关闭方会重发 FIN,主动关闭方留在 TIME_WAIT 才能再次回应。CLOSE_WAIT 没有类似的协议定时器替应用收尾:只要代码没有走到 close(),文件描述符就会一直占着。因此前者先查连接模型,后者优先查应用代码和线程栈。


四、TCP 可靠传输与流量控制

知识点

  • 字节流与序列号:TCP 面向连续字节流,不保留应用消息边界;序列号标记字节位置,接收方用确认号表示下一段期望收到的字节。
  • 确认与校验:TCP 使用校验和发现传输损坏,确认通常是累计确认;乱序段可以先缓存,缺口补齐后再把连续数据交给应用。
  • 超时重传:发送方根据采样 RTT 及其波动动态估算重传超时,超时仍未确认就重发;固定超时时间无法同时适应局域网和跨洲链路。
  • 快速重传:经典算法收到 3 个重复 ACK 后,不等重传计时器到期就重发疑似丢失段;SACK 可进一步告诉发送方哪些区间已经收到。
  • 滑动窗口:发送方可在未逐段等待 ACK 的情况下连续发送窗口内的数据,用流水线提高带宽利用率;确认推进后窗口继续向前滑动。
  • 接收窗口:接收方通告 rwnd 限制未确认数据量,防止发送速度超过接收缓冲区和应用处理能力;窗口为零时,发送方用窗口探测等待恢复。

面试问答

  • Q1:TCP 如何保证可靠传输?(高频)

A: 可以抓住序列号、确认、重传和窗口来答。序列号负责排序与去重,校验和发现损坏,累计 ACK 表示连续收到哪里;丢包后由超时或重复 ACK 触发重传。滑动窗口让多段数据同时在途,接收窗口再限制发送量。

W: 如果每发一个报文都等一次确认,带宽很高但往返时延较大的链路也跑不满。滑动窗口允许一批数据同时在路上;其中一段丢失时,后续段会让接收方重复确认缺口,发送方可以提前重传。序列号把并行、乱序和重传重新拼成有序字节流。


五、TCP 拥塞控制(高频)

知识点

  • 两种窗口:接收窗口 rwnd 保护接收端,拥塞窗口 cwnd 保护网络;发送方实际可发送的在途数据受两者较小值约束。
  • 慢启动:连接开始或严重拥塞后,从较小的拥塞窗口探测容量;每收到确认都会增加窗口,整体表现为每个 RTT 近似翻倍,并不是真的速度慢。
  • 拥塞避免:达到慢启动门限 ssthresh 后改为较温和的线性增长,避免继续指数扩张迅速压垮链路。
  • 快速重传与恢复:经典 Reno 收到 3 个重复 ACK 后判断出现局部丢包,立即重传并降低窗口;快速恢复避免像超时那样完全退回起点。
  • 算法边界:慢启动、拥塞避免、快速重传和快速恢复是经典面试框架;现代系统还可能使用 CUBIC、BBR 等算法,窗口增长细节不能一概按 Reno 描述。

面试问答

  • Q1:流量控制和拥塞控制有什么区别?(高频)

A: 记住各自保护谁:流量控制保护接收端,由接收方通告 rwnd;拥塞控制保护中间网络,由发送方根据丢包、时延等信号调整 cwnd。实际发送窗口取两者较小值,所以接收端很空闲,也不代表发送方能无视网络拥塞。

W: 接收方机器很慢,即使网络空闲,也应该缩小接收窗口;反过来,接收方内存充足,但共享出口已经排队丢包,仍要缩小拥塞窗口。只做流量控制会继续把中间路由器打满,只做拥塞控制又可能冲垮接收缓冲区,所以 TCP 同时维护两套约束。


六、TCP、UDP 与粘包(高频)

知识点

  • TCP 特征:TCP 面向连接,提供可靠、有序、去重的字节流;首部最小 20 字节,还要维护握手、重传、窗口和连接状态。
  • UDP 特征:UDP 面向数据报,首部固定 8 字节,不保证交付、顺序或去重;应用能保留每个数据报的边界,但要自行处理可靠性需求。
  • 场景选择:文件和交易数据通常需要 TCP;实时音视频、语音通话和简单查询常接受少量丢包以换低等待,也可以基于 UDP 自建可靠机制。
  • QUIC 的位置:QUIC 报文承载在 UDP 数据报中,但在用户态实现可靠传输、多路流、拥塞控制和 TLS;“基于 UDP”不等于“不可靠”。
  • 粘包拆包:TCP 只提供字节流,一次 send() 与一次 recv() 没有一一对应关系;应用协议需要固定长度、分隔符或“长度字段 + 消息体”定义边界。

面试问答

  • Q1:TCP 和 UDP 应该怎么选?(高频)

A: 别只按谁快来选。支付、文件传输不能缺字节,通常用可靠有序的 TCP;实时语音更怕等待,可以用 UDP,让应用自己决定丢包、重传和过期策略。UDP 首部更小也没有握手,但不天然更快,QUIC 仍在其上补了可靠传输。

W: 视频帧晚到两秒,即使完整也可能没有播放价值,等待 TCP 重传反而造成卡顿;转账指令少一个字节却可能改变业务含义,必须可靠到达。协议选择不是简单比较速度,而是决定“丢失、乱序、延迟”发生时由谁处理,以及业务愿意付出什么代价。

  • Q2:TCP 为什么会粘包,怎么解决?

A: 粘包本身是正常的。TCP 只管字节流,不保留消息边界,连续两次写入可能一次读到,也可能拆成多次。应用协议得自己定界,可以用固定长度、特殊分隔符,或者“长度字段 + 消息体”;接收端凑够长度后再交给业务。

W: 假设客户端先发送“长度 5 + hello”,再发送“长度 3 + bye”,内核可以为了效率合并写入,网络也可能把数据拆段。接收端若把一次 recv() 当成一条消息,就会误读。长度字段让接收端不依赖底层分段方式,凑够指定字节再交给业务。


七、HTTP 语义与版本演进(高频)

知识点

  • 方法语义:GET、HEAD、OPTIONS 属于安全方法;PUT、DELETE 在协议语义上幂等,POST 不保证幂等。幂等指相同请求执行多次的预期效果相同,不代表响应必须完全一致。
  • 状态码分组:2xx 表示成功,3xx 表示重定向或缓存结果,4xx 是客户端侧问题,5xx 是服务端处理失败;排查时还要结合具体状态码与响应头。
  • HTTP/1.1:默认使用持久连接,减少重复建连;管线化要求响应按请求顺序返回,前面的慢响应会阻塞后续响应,浏览器实际使用有限。
  • HTTP/2:使用二进制帧、HPACK 头部压缩和多路复用,一条 TCP 连接可并发承载多个流;TCP 丢包时,所有流仍会一起等待缺失字节。
  • HTTP/3:把 HTTP 映射到 QUIC,每个请求响应使用独立 QUIC 流;一个流丢包不会阻止其他流继续处理,并把 TLS 1.3 集成进连接建立。
  • 常考状态码:301/308 常用于永久重定向,302/307 常用于临时重定向,其中 307/308 明确保留原方法;401 表示需要认证,403 表示服务器拒绝授权。

面试问答

  • Q1:HTTP/1.1、2、3 解决了什么?(高频)

A: 这条演进线围绕连接和阻塞展开。HTTP/1.1 用持久连接减少握手,HTTP/2 再用分帧和多路复用并发跑多个流,但 TCP 丢包仍会卡住全部流。HTTP/3 改用 QUIC,把丢包影响限制在单个流,还把 TLS 1.3 合进连接建立。

W: 页面同时请求 CSS、脚本和图片时,HTTP/1.1 往往要开多条连接绕过排队;HTTP/2 能把它们交错放进一条连接。可这条连接底下仍是一条有序 TCP 字节流,缺一个字节,后面的流都不能越过。QUIC 把可靠顺序限制在单个流内,其他流可以继续。

  • Q2:常见 HTTP 状态码怎么区分?

A: 先按责任分组:2xx 成功,3xx 重定向或缓存,4xx 是请求侧问题,5xx 是服务端失败。容易混的是 401 需要认证、403 拒绝授权,以及网关收到无效响应的 502 和等待上游超时的 504。

W: 请求经过网关访问业务服务时,业务服务及时返回拒绝,网关可以原样给出 403;上游进程崩溃或返回不了合法协议,网关可能给 502;连接存在但迟迟没有响应,则更像 504。状态码是链路某一层的判断,必须结合网关和应用日志定位。


八、HTTP 缓存(高频)

知识点

  • 新鲜度缓存:响应在 Cache-Control: max-age=N 指定时间内可直接复用,不必访问源服务器;共享缓存还要关注 s-maxage、public 和 private。
  • no-cache 与 no-store:no-cache 允许保存响应,但每次复用前必须向源站验证;no-store 要求缓存不得存储请求或响应内容,两者含义不同。
  • ETag 验证:客户端携带 If-None-Match,资源标识未变化时服务端返回 304 Not Modified,客户端继续使用本地正文。
  • 时间验证:Last-Modified 配合 If-Modified-Since 使用,精度和语义通常弱于实体标签;两种验证器同时存在时应优先按 ETag 判断。
  • Vary:Vary 告诉共享缓存哪些请求头会改变响应,例如压缩编码或语言;缺失会让缓存把一个版本错误地发给其他请求。

面试问答

  • Q1:强缓存和协商缓存怎么工作?(高频)

A: 资源在 Cache-Control 的 max-age 内就直接用。过期后带 If-None-Match 或 If-Modified-Since 验证;没变就收不带正文的 304,复用本地内容,变了再收新的 200。

W: 一张长期不变的带哈希文件名图片适合设置很长的 max-age,发布新版本时换 URL,不必频繁验证。HTML 入口经常变化,可以保存但每次带 ETag 验证。若误把 no-cache 理解成完全不缓存,就会放弃 304 节省正文传输的价值;真正禁止存储的是 no-store。


九、HTTPS 与 TLS(大厂高频)

知识点

  • HTTPS 目标:TLS 在 HTTP 与传输层之间提供机密性、完整性和身份认证;加密只能保护传输链路,不能自动修复服务端漏洞或恶意业务逻辑。
  • 混合密码体系:证书私钥签名和密钥交换用于认证并协商共享秘密,后续数据用对称密钥加密;对称加密适合大流量,非对称机制解决身份与密钥建立问题。
  • 证书链:服务器证书由中间 CA 签发,再逐级连接到客户端信任的根 CA;客户端还会校验域名、有效期、用途和签名链。
  • TLS 1.3 握手:客户端在 ClientHello 中发送支持参数和密钥份额,服务端选择参数并发送证书及握手签名;双方导出会话密钥后,完整握手通常一个 RTT 即可发送应用数据。
  • 前向保密:TLS 1.3 的常规密钥交换使用临时 Diffie-Hellman 类方案;以后即使证书私钥泄露,过去抓到的会话密文也不能仅靠该私钥解开。
  • 0-RTT 边界:恢复旧会话时客户端可提前发送数据,但 0-RTT 存在重放风险,只应承载能够安全重复执行的请求。

面试问答

  • Q1:TLS 1.3 握手过程是什么?(高频)

A: 客户端先发 ClientHello,带算法列表和密钥份额;服务端返回选择结果、自己的密钥份额、证书和握手签名。客户端验证证书链、域名与签名,双方再从密钥交换结果导出对称会话密钥。后续 HTTP 数据都用这组临时密钥保护。

W: 证书只证明公钥属于目标域名,不能直接拿来高效加密整段视频。握手先用证书签名确认服务端身份,再通过临时密钥交换算出只有双方知道的共享秘密,最后派生读写密钥。攻击者即使截获全部报文,没有私钥材料和临时秘密也无法伪造握手或解密内容。

  • Q2:HTTPS 为什么混合两类加密?

A: 两类算法解决的问题不同。非对称机制适合认证身份和建立共享秘密,但计算成本高;对称加密适合保护大量数据,前提是双方安全拿到同一把密钥。TLS 在握手阶段完成认证和协商,后续流量再交给临时对称密钥。

W: 如果全程用公钥算法加密每个响应块,CPU 成本会很高;若一开始就直接发送对称密钥,旁路监听者也能拿到。TLS 让服务端先用证书证明身份,再通过密钥交换得到共享秘密,对称密钥不需要明文穿过网络。两类算法解决的是不同问题。


十、Cookie、Session 与 Token(高频)

知识点

  • Cookie:服务端用 Set-Cookie 让浏览器保存键值,浏览器按域、路径、安全属性等规则在后续请求的 Cookie 头中自动携带。
  • Session:服务端保存登录状态,客户端通常只持有随机 Session ID;状态容易立即撤销,但多实例部署需要共享、复制或固定路由。
  • Token:客户端持有访问凭证,常放在 Authorization: Bearer 中;服务端可以查库验证,也可以验证自包含令牌的签名和声明。
  • JWT 边界:常见 JWT 是 header.payload.signature 的 JWS 紧凑格式,签名保证内容未被篡改,不代表载荷已加密;敏感信息不能因为做了 Base64URL 编码就直接放入。
  • 撤销与续期:自包含 Token 减少集中 Session 查询,但即时注销、权限变更和令牌泄露处理更复杂,通常需要短有效期、刷新令牌或服务端撤销表。
  • Cookie 安全属性:Secure 限制安全连接发送,HttpOnly 阻止脚本直接读取,SameSite 限制跨站携带;这些属性分别缓解窃听、XSS 盗取和 CSRF,不能互相替代。

面试问答

  • Q1:Cookie、Session、Token 怎么区分?(高频)

A: 这三个概念不在同一层。Cookie 是浏览器自动携带数据的机制;Session 是服务端状态,Cookie 常只存其 ID;Token 是客户端主动发送的凭证。Session 好撤销但要存状态,Token 方便跨服务验证,却更难即时失效。

W: 用户退出登录时,服务端删除 Session,原 Session ID 立刻失效。自包含 Token 已经签发,资源服务只验签而不查中心状态,就无法立刻知道用户退出或权限被收回。想兼顾扩展性与撤销能力,需要缩短访问令牌寿命,再配刷新令牌、版本号或黑名单。

  • Q2:JWT 为什么不能直接当加密数据?

A: 编码不等于加密。常见 JWT 用 JWS 签名,载荷只是 Base64URL 编码,拿到令牌就能读。签名证明内容没被改、来自可信签发方,却不负责隐藏内容。密码、身份证号等敏感信息不能直接放进去,需要保密就用 JWE 或另做加密。

W: 服务端把 userId 和角色写进 JWT 后签名,客户端虽然能读到内容,却不能把普通用户改成管理员,因为签名会失效。这解决的是完整性,不是机密性。若把密码也放进去,攻击者无需伪造签名就能读取,因此“能验签”和“看不见内容”必须分开讨论。


十一、URL 全链路与故障排查(综合题)

知识点

  • 请求前准备:浏览器解析 URL,检查 HSTS、Service Worker 和可用缓存,再决定协议、目标地址及是否需要发起网络请求。
  • 网络建立:DNS 得到 IP 后,主机按路由表选择下一跳并解析链路层地址;HTTP/1.1、HTTP/2 通常先建 TCP 再做 TLS,HTTP/3 使用基于 UDP 的 QUIC。
  • 请求与响应:浏览器发送 HTTP 请求,流量可能依次经过 CDN、负载均衡、网关和应用;服务端返回状态码、响应头和正文,重定向会触发新的请求链路。
  • 页面渲染:浏览器解析 HTML 构建 DOM,解析 CSS 构建 CSSOM,生成渲染树后执行布局、绘制和合成;脚本与子资源下载可能改变或阻塞这条流程。
  • 分段排查:把耗时拆成 DNS、连接、TLS、首字节、内容下载和渲染阶段,再结合浏览器 Network/Performance、curl -w、DNS 工具和服务端链路日志定位。
  • WebSocket:经典握手通过 HTTP/1.1 Upgrade: websocket 请求,服务端返回 101 Switching Protocols 后进入全双工帧通信;长连接还要处理心跳、断线重连和代理空闲超时。

面试问答

  • Q1:输入 URL 到页面展示发生了什么?(高频中的高频)

A: 可以按名字、连接、请求、渲染四段回答。浏览器检查缓存后用 DNS 找到 IP,再建立 TCP 与 TLS,或直接建立 QUIC。接着发送 HTTP 请求,收到响应后解析 HTML 和 CSS,执行脚本、加载子资源,最后完成布局、绘制和合成。

W: 这条链路跨越了应用、传输、网络和链路层:DNS 只解决名字到地址,ARP 只解决本地下一跳,TCP 或 QUIC 负责端到端传输,TLS 建立可信加密通道,HTTP 才表达业务请求。页面拿到 HTML 也不等于完成展示,脚本和样式仍可能阻塞渲染。

  • Q2:网页打开慢怎么定位?(排查题)

A: 别一上来就猜后端慢。先按时间线拆 DNS、建连、TLS、TTFB、下载和渲染:DNS 慢查解析器,建连慢查丢包与路由,TTFB 高再查网关、应用和数据库;下载慢看体积与带宽,渲染慢用 Performance 面板找长任务。

W: 如果首字节前等了两秒、正文下载只用几十毫秒,压缩图片不会解决问题;应继续拆 DNS、连接和服务端处理。反过来,接口很快但页面迟迟不可交互,就要看脚本执行、布局和资源依赖。先按阶段归因,才能避免拿后端扩容去治前端阻塞。

  • Q3:WebSocket 和 HTTP 长轮询怎么选?

A: 服务端要频繁主动推送、双方都要低延迟发消息时,用 WebSocket,比如聊天和协作编辑。更新很少,或者基础设施只支持普通 HTTP,长轮询更省事。WebSocket 建连后请求开销低,但心跳、重连、消息确认和连接扩容都得自己处理。

W: 通知一天只来几次,却维持百万条长连接,会持续占用文件描述符、网关连接和心跳流量,长轮询可能更省运维成本。聊天消息每秒都在变化,长轮询会反复建立请求并增加延迟,此时全双工连接更合适。选择取决于消息频率、延迟和连接规模。