网络编程协议面试经典

发布时间:2026/7/30 3:47:35
网络编程协议面试经典 1. 引言在技术面试中网络基础与缓存算法是两大必问方向。本文将围绕三个高频考点展开TCP 三次握手与四次挥手、从输入 URL 到页面展示的完整过程、以及LRU 缓存淘汰策略的实现与应用。这三者看似独立实则共同构成了现代 Web 应用在数据传输、资源加载和性能优化层面的核心知识体系。2. TCP 三次握手三次握手是 TCP 协议建立可靠连接的过程发生在客户端与服务器之间。其核心目的是同步双方的序列号、确认双方的收发能力正常。2.1 三次握手过程第一次握手——SYN客户端发送一个 SYN同步报文给服务端其中包含一个随机生成的初始序列号 seqx客户端进入SYN_SENT状态。第二次握手——SYNACK服务端收到 SYN 报文后确认客户端的发送能力和自己的接收能力均正常。服务端发送一个 SYNACK 报文ackx1 表示确认已收到客户端的数据seqy 为服务端的初始序列号。此时服务端进入SYN_RCVD状态。第三次握手——ACK客户端收到 SYNACK 后发送 ACK 报文acky1seqx1。此时客户端进入ESTABLISHED状态。服务端收到 ACK 后也进入ESTABLISHED状态至此双向连接建立。2.2 关键问题为什么不是两次握手两次握手只能确认客户端的发送能力和服务端的接收能力无法确认服务端的发送能力和客户端的接收能力。如果只有两次握手服务端在收到 SYN 后就会认为连接已建立无法保证客户端是否收到了自己的回复也无法防止旧的重复连接请求导致的资源浪费。为什么不是四次握手第二次握手时服务端可以将 SYN 和 ACK 合并到一起发送效率更高。分开发送会增加一次不必要的往返没有实际意义。SYN 泛洪攻击攻击者伪造大量不存在 IP 的 SYN 报文服务端在SYN_RCVD状态分配大量资源后得不到回复最终耗尽半连接队列。防御方式包括 SYN Cookie、减少超时重传次数、增加半连接队列容量等。3. TCP 四次挥手四次挥手是 TCP 连接断开的过程由于 TCP 的连接是全双工的每个方向都需要单独关闭因此需要四次报文交互。3.1 四次挥手过程第一次挥手——FIN主动关闭方发送 FIN 报文finishsequ表示本端数据已发送完毕主动方进入FIN_WAIT_1状态。第二次挥手——ACK被动关闭方收到 FIN 后回复 ACKacku1seqv。被动方进入CLOSE_WAIT状态主动方收到 ACK 后进入FIN_WAIT_2状态。此时半关闭状态主动方不能再发送数据但仍可接收被动方发来的数据。第三次挥手——FIN被动关闭方数据发送完毕后也发送 FIN 报文seqwack 仍为 u1。被动方进入LAST_ACK状态。第四次挥手——ACK主动方收到 FIN 后回复 ACKackw1sequ1并进入TIME_WAIT状态。等待 2MSL最大报文生存时间的两倍后进入CLOSED状态。被动方收到 ACK 后立即进入CLOSED状态。3.2 关键问题为什么要四次挥手TCP 是全双工的当一方完成数据发送时可以发送 FIN 告知对方但对方可能还有未发送完的数据因此需要先确认收到 FIN等自身数据也发送完毕后再发送 FIN。这两个阶段分开执行共需四次报文。TIME_WAIT 为什么要等待 2MSL一是确保最后一个 ACK 能被被动方接收到如果 ACK 丢失被动方会重发 FIN主动方可以重新回复 ACK二是让本次连接的所有报文从网络中消失防止旧连接的报文被新连接误收。2MSL 保证了两个方向上的报文都失效。大量 TIME_WAIT 状态如何解决常见手段包括开启tcp_tw_reuse复用 TIME_WAIT 连接、调整tcp_tw_recycle、缩短tcp_fin_timeout、使用长连接或连接池减少频繁建连断连。3.3 三次挥手与四次挥手的对比维度三次握手四次挥手阶段连接建立连接释放报文数量3 个4 个触发方客户端主动发起任意一方均可发起可否合并ACK 与 SYN 合并ACK 与 FIN 分开发送特殊状态SYN_SENT、SYN_RCVDTIME_WAIT、CLOSE_WAIT4. 从输入 URL 到页面展示的完整过程这是一道经典的综合性面试题考察候选人对网络协议、浏览器原理、操作系统和前端渲染的全链路理解。整个过程可分为以下几个阶段4.1 URL 解析浏览器首先解析用户输入的 URL判断是搜索关键词还是合法 URL。如果输入的是非 URL 文本浏览器会使用默认搜索引擎进行搜索如果是合法 URL则拆分出协议如https、域名如www.example.com、端口默认 443 或 80、路径和查询参数等。4.2 DNS 域名解析浏览器按以下顺序查找域名的 IP 地址浏览器 DNS 缓存→操作系统 hosts 文件→操作系统 DNS 缓存→本地 DNS 服务器。如果本地 DNS 服务器未命中则进行递归查询从根域名服务器逐级向下解析最终获取目标 IP 地址。DNS 解析优化手段包括DNS 预解析link reldns-prefetch、CDN 就近解析、减少域名数量等。4.3 建立 TCP 连接获取到目标服务器的 IP 地址后浏览器通过三次握手与服务器建立 TCP 连接。如果需要 HTTPS则先通过 TCP 连接进行 SSL/TLS 四次握手客户端发送 ClientHello → 服务端回复 ServerHello 和证书 → 客户端验证证书并交换密钥 → 双方确认加密通信开始。4.4 发送 HTTP 请求连接建立后浏览器发送 HTTP 请求报文包含请求行方法、路径、协议版本、请求头Cookie、User-Agent、Accept 等和请求体如果是 POST/PUT 请求。HTTP/2 和 HTTP/3 对这部分有进一步优化如多路复用、头部压缩等。4.5 服务器处理请求并响应请求经过负载均衡、反向代理到达后端服务器。服务器解析请求执行业务逻辑查询数据库、调用微服务等生成 HTTP 响应报文返回给浏览器。响应报文包含状态行如200 OK、301 Moved Permanently、响应头Content-Type、Cache-Control、Set-Cookie 等和响应体HTML、JSON 等。4.6 浏览器解析与渲染浏览器收到 HTML 后启动渲染流程构建 DOM 树解析 HTML 字节流构建文档对象模型树。构建 CSSOM 树解析 CSS 样式表构建 CSS 对象模型树。执行 JavaScript遇到script标签时暂停 DOM 解析下载并执行 JS 代码async和defer可改变执行时机。JS 可能会修改 DOM 和 CSSOM。构建渲染树合并 DOM 树和 CSSOM 树剔除不可见元素如display:none生成渲染树。布局计算每个渲染树节点的几何位置和尺寸。绘制将各节点绘制到屏幕上按图层分别进行光栅化最终合成显示。4.7 四次挥手断开连接页面数据加载完毕后如果使用 HTTP/1.0 的短连接此时会进行四次挥手断连HTTP/1.1 默认使用长连接Connection: keep-alive在一定时间内保持 TCP 连接以复用。5. LRU 缓存淘汰算法LRULeast Recently Used最近最少使用是一种经典的缓存淘汰策略当缓存空间满时优先淘汰最近最少被访问的数据。其核心思想是认为近期被访问过的数据在未来也更有可能被访问而长期未被访问的数据在未来被访问的概率较低。5.1 核心实现哈希表 双向链表LRU 要求在O(1)时间复杂度内完成get和put操作。哈希表负责快速定位节点双向链表负责维护访问顺序。每次访问或插入时将节点移到链表头部淘汰时从链表尾部删除。5.2 Java 实现示例public class LRUCache { private MapInteger, Node map; private Node head, tail; private int capacity; static class Node { int key, value; Node prev, next; Node(int key, int value) { this.key key; this.value value; } } public LRUCache(int capacity) { this.capacity capacity; map new HashMap(); head new Node(0, 0); tail new Node(0, 0); head.next tail; tail.prev head; } public int get(int key) { Node node map.get(key); if (node null) return -1; moveToHead(node); return node.value; } public void put(int key, int value) { Node node map.get(key); if (node ! null) { node.value value; moveToHead(node); return; } Node newNode new Node(key, value); map.put(key, newNode); addToHead(newNode); if (map.size() capacity) { Node removed removeTail(); map.remove(removed.key); } } private void addToHead(Node node) { node.next head.next; head.next.prev node; head.next node; node.prev head; } private void removeNode(Node node) { node.prev.next node.next; node.next.prev node.prev; } private void moveToHead(Node node) { removeNode(node); addToHead(node); } private Node removeTail() { Node node tail.prev; removeNode(node); return node; } }5.3 LRU 的变体与优化LRU-K记录每个数据最近 K 次访问的时间戳淘汰最久远的一次。相比基础 LRU更能抵抗偶发性访问对缓存页面的污染。Two-Queue LRU维护两个队列数据先进入FIFO队列被再次访问时移入LRU队列淘汰时优先淘汰FIFO队列。Redis 中的近似 LRURedis 默认采用近似 LRU 算法随机采样若干个键淘汰其中最久未访问的一个既降低了实现复杂度也在大多数场景下保持了较好的命中率。LRU 在操作系统中的应用操作系统使用近似 LRU如时钟算法进行页面置换通过硬件支持的引用位来近似追踪页面访问情况避免维护完整链表的开销。5.4 LRU 在浏览器缓存中的应用浏览器的内存缓存Memory Cache在一定程度上遵循 LRU 策略。当浏览器缓存达到上限时会优先淘汰最近最少使用的资源如图片、CSS、JS 文件。结合 HTTP 缓存头Cache-Control、ETag 等可以对资源进行更精确的缓存控制。前端开发中可以通过合理设置缓存策略、减少缓存体积以及利用 Service Worker 进一步实现对缓存淘汰的精细化控制。6. 总结TCP 的三次握手和四次挥手奠定了互联网数据传输的可靠性基础从 URL 到页面的渲染过程则串联起了域名解析、网络传输、浏览器内核三大体系。LRU 缓存策略在操作系统、数据库、Redis 以及浏览器缓存中都有着广泛应用。这三个知识点相互关联共同构成了后端与前端工程师必备的基础能力。建议在实际面试准备中做到能画流程图讲清握手挥手过程、能举出 TIME_WAIT 和 CLOSE_WAIT 的真实场景、能手写 LRU 的 O(1) Java 实现、能从 URL 出发串联完整的网络与渲染链路。