计网八股分析

计网八股分析
mengnankkzhou计网
1.对比一下 HTTP/1.0, HTTP/1.1, 和 HTTP/2.0 这三个版本的主要区别。
请从连接管理、性能优化、头部处理等角度展开,并说明每一个版本的演进分别解决了上一代的什么核心痛点?
1.0->1.1
- 长链接 (Keep-Alive): 是 HTTP/1.1 相对于 HTTP/1.0 最核心的改进之一。HTTP/1.0 默认是短连接,每个请求/响应对都需要一次 TCP 连接。而 HTTP/1.1 默认开启了长链接,允许在一个 TCP 连接上发送多个 HTTP 请求,极大地减少了 TCP 连接建立和关闭的开销。
- HTTP/1.1 还引入了管道机制 (Pipelining),允许客户端在收到上一个响应之前就发送下一个请求。但这只是部分解决了队头阻塞(Head-of-Line Blocking)问题,因为服务端的响应仍然必须按顺序返回。
2.0
- 多路复用 (Multiplexing): 这是 HTTP/2.0 最核心的优势。它允许在一个 TCP 连接上,同时、并行地收发多个请求和响应,并且不按顺序。这彻底解决了 HTTP/1.1 的队头阻塞问题。
- 头部压缩 (Header Compression): HTTP/2.0 使用 HPACK 算法来压缩请求和响应的头部。对于多个请求,很多头部字段是重复的,HPACK 可以极大地减少这部分的数据传输量。
- 服务器推送 (Server Push): 服务器可以主动地将客户端未来可能会用到的资源(如 CSS, JS 文件)提前推送到客户端缓存中,减少了请求的 RTT(往返时间)。
- 二进制分帧 (Binary Framing): 这是 HTTP/2.0 的革命性变化。HTTP/1.0 和 1.1 都是基于文本的协议,而 HTTP/2.0 将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码。这解决了 1.x 时代基于文本的协议解析效率低的问题。
- HTTP/1.0 -> HTTP/1.1: 解决了什么?连接无法复用的问题。通过什么解决?默认开启长链接 (Keep-Alive)。
- HTTP/1.1 -> HTTP/2.0: 解决了什么?队头阻塞和头部冗余的问题。通过什么解决?二进制分帧、多路复用、头部压缩。
2.从用户在浏览器输入 URL 到页面渲染完成,请按网络与系统角度分层讲解关键路径。
我将其分为请求准备阶段、网络通信阶段、和浏览器渲染阶段
当我在URL栏输入地址的话,首先要知道这个域名对应的IP地址是啥
请求准备:
- 浏览器首先会解析URL,判断协议(HTTPS)、域名www.google.com)、端口(默认为443)等信息。接着,它会查询自己的浏览器缓存,看之前是否已经解析过这个域名并且缓存还未过期。如果命中,就直接使用缓存的IP地址,跳过后续的DNS查询。
- 如果浏览器缓存未命中,操作系统会启动一个DNS查询流程,这是一个从近到远、层层递归的查询过程,核心目标是将域名转换为IP地址。先是操作系统&host文件,然后是本地DNS服务器,再是根域名服务器,顶级域名服务器,权威域名服务器。依次类推
- LDNS拿到IP地址后,会将其缓存起来,并返回给操作系统,操作系统再返回给浏览器。至此,DNS解析完成。
网络通信:
这个过程涉及到TCP、TLS和HTTP三个核心协议
TCP三次握手
- 第一次握手 (SYN):客户端随机选择一个初始序列号
client_isn,将TCP报文段的SYN标志位置为1,然后发送给服务器。此时客户端进入SYN_SENT状态。 - 第二次握手 (SYN+ACK):服务器收到SYN包后,必须确认客户端的
SYN。它将报文段的SYN和ACK标志位都置为1,确认号ack设为client_isn + 1,同时自己也选择一个初始序列号server_isn,然后发送给客户端。此时服务器进入SYN_RCVD状态。 - 第三次握手 (ACK):客户端收到服务器的SYN+ACK包后,检查确认号是否正确。如果正确,它会将
ACK标志位置为1,确认号ack设为server_isn + 1,然后发送给服务器。这个ACK包可以携带数据。发送后,客户端和服务器都进入ESTABLISHED状态,连接建立成功。
TLS四次挥手:
- Client Hello:客户端发送支持的TLS版本、加密套件列表、以及一个随机数
client_random。 - Server Hello & Certificate:服务器选择一个加密套件,返回自己的数字证书、以及一个随机数
server_random。 - 客户端验证与密钥交换:客户端验证服务器证书的有效性。验证通过后,生成一个预主密钥
pre-master secret,用服务器证书中的公钥加密后发送给服务器。 - 服务器解密与会话密钥生成:服务器用自己的私钥解密,得到
pre-master secret。至此,客户端和服务器双方都拥有了client_random、server_random和pre-master secret,它们使用相同的算法,各自独立地生成一个对称的会话密钥。 - Finished:双方互发
Finished消息,用生成的会话密钥加密,验证握手过程是否成功。握手结束后,后续所有的HTTP数据都将使用这个对称的会话密钥进行加密传输。
Http请求和相应:
- 发送HTTP请求:浏览器构建一个HTTP请求报文,包含请求行(
GET / HTTP/1.1)、请求头(Host,User-Agent,Cookie等)和请求体(GET请求通常为空),然后通过建立好的TCP/TLS通道发送给服务器。 - 请求到达服务器后,可能会先经过负载均衡器(如Nginx/SLB),它会将请求转发到后端的某一台应用服务器。
- 应用服务器(如Tomcat)接收到请求后,Web容器会解析HTTP报文,将其封装成
HttpServletRequest对象。 - 业务代码(如Spring MVC的Controller)被调用,它可能会查询缓存(Redis)、数据库(MySQL),执行业务逻辑,最终生成数据。
- 服务器将数据渲染进HTML模板,构建一个HTTP响应报文,包含状态行(
HTTP/1.1 200 OK)、响应头(Content-Type,Set-Cookie等)和响应体(HTML内容)。 - 接收HTTP响应:浏览器接收到服务器的响应报文。
浏览器渲染:
- 浏览器自上而下解析HTML文档,生成DOM树(Document Object Model)。
- 在解析过程中,如果遇到
<link>标签引用的CSS文件,会异步下载并解析,生成CSSOM树(CSS Object Model)。 - 如果遇到
<script>标签,会阻塞DOM的解析,立即下载并执行JavaScript代码(除非script标签有async或defer属性)。 - 构建渲染树(Render Tree):将DOM树和CSSOM树结合起来,生成渲染树。渲染树只包含需要被显示的节点及其样式信息(例如,
display:none的节点就不会在渲染树中)。 - 布局(Layout/Reflow):浏览器根据渲染树,计算出每个节点在屏幕上的精确位置和大小。
- 绘制(Paint/Rasterizing):浏览器调用GPU,根据布局信息,将每个节点绘制成屏幕上的实际像素。
- 合成(Composite):对于复杂的页面(如使用了
transform或opacity),浏览器会将页面分层,独立绘制,最后再合成到一起,以提升性能。
所有资源加载完成,或者是空闲超时了之后,就会开始断开请求TCP的四次挥手
- 第一次挥手 (FIN):主动关闭方(如客户端)发送一个
FIN报文,表示自己的数据已发送完毕。进入FIN_WAIT_1状态。 - 第二次挥手 (ACK):被动关闭方(服务器)收到
FIN后,回复一个ACK报文。此时,连接处于半关闭状态,服务器仍然可以向客户端发送数据。 - 第三次挥手 (FIN):服务器也准备好关闭连接时,发送一个
FIN报文给客户端。进入LAST_ACK状态。 - 第四次挥手 (ACK):客户端收到服务器的
FIN后,回复一个ACK报文。发送后,客户端进入TIME_WAIT状态。服务器收到这个ACK后,立即关闭连接。
TIME_WAIT状态?
- 可靠地终止TCP连接:这是最主要的原因。四次挥手中的最后一个ACK报文是由主动关闭方(客户端)发出的。这个ACK报文有可能会在网络中丢失。如果丢失,被动关闭方(服务器)就收不到确认,它会超时重传它的FIN报文。如果此时客户端已经彻底关闭连接,它将无法响应这个重传的FIN,导致服务器永远无法正常关闭。而处于
TIME_WAIT状态的客户端,仍然能接收到这个重传的FIN,并重新发送一次ACK,从而确保服务器能够正常关闭。 - 防止已失效的报文段被新连接误接收:考虑一个场景:一个TCP连接(由
源IP:源端口, 目的IP:目的端口这个四元组唯一标识)关闭后,马上又用完全相同的四元组建立了一个新的连接。此时,网络中可能还存在上一个旧连接中延迟到达的报文段。如果没有TIME_WAIT状态,这些“迷路”的旧报文段就可能会被这个新连接误认为是合法数据并接收,造成数据错乱。
为什么等待时间是 2MSL?
- MSL(Maximum Segment Lifetime)\是指一个TCP报文段在网络中可能存活的*最长时间*。任何报文在超过MSL后,都会被网络丢弃。
2MSL的时间足以保证在一个连接的一去一回两个方向上,所有的报文段都能在网络中自然消失。当TIME_WAIT状态结束后,可以保证网络中不再有任何与旧连接相关的“幽灵”报文段,此时再建立新的连接就是完全安全的。
3.在 TCP 三次握手过程中,如果第三次握手的 ACK 报文丢失了,会发生什么?
三次握手分别是:
1 | SYN` -> `SYN+ACK` -> `ACK |
- 服务端状态: 当服务端发送完
SYN+ACK之后,它会进入SYN_RCVD状态,并启动一个定时器,等待客户端的第三次ACK。 - 客户端状态: 当客户端发送完第三次
ACK之后,它单方面认为连接已经建立,状态会变为ESTABLISHED。
因为是服务端在 SYN_RCVD 状态下等待第三次 ACK 超时了。当定时器超时后,服务端会重新发送 SYN+ACK 包给客户端。重传的次数由系统参数(如 net.ipv4.tcp_synack_retries)控制。
在 SYN_RCVD 状态下,连接并未完全建立。对于服务端应用层来说,它通过 accept() 拿到的连接还处于一个“半连接队列”中,应用层是无法使用这个连接的,所以服务端应用层无感知。
因为客户端在发送完第三次 ACK 后,其内核协议栈就认为连接已建立(ESTABLISHED 状态),所以对于客户端应用层来说,connect() 系统调用会立即返回成功。此时,客户端应用层会认为连接已经建立成功,并开始发送数据。
处理:
- 客户端应用层发送的数据,会和因为第三次 ACK 丢失而重传的
SYN+ACK在网络中交汇。 - 当客户端收到服务端重传的
SYN+ACK后,它的内核会意识到自己之前发送的ACK可能丢失了,于是会再次发送一个ACK给服务端。 - 当服务端收到了这个新的
ACK后(无论是客户端重发的,还是伴随着数据包一起过来的),服务端状态才会变为ESTABLISHED,连接才真正建立,之前客户端发送的数据才会被服务端应用层接收。
TCP状态机转变:CLOSED->SYN_SENT->SYN_RCVD->ESTABLISHE
评论
匿名评论隐私政策
TwikooValine
✅ 你无需删除空行,直接评论以获取最佳展示效果












