网络知识点汇总
谈起计算机网络,不得不祭出这张图。
# 1. 当浏览器输入一个url请求会经历什么?
主要流程大致如下:
- DNS 域名解析
- 建立 TCP 连接(三次握手)
- 发起 HTTP 请求(Request)
- 服务器处理请求,浏览器接受 HTTP 响应(Response)
- 浏览器解析渲染页面
- 连接结束(四次挥手) 下面解释下各部分。
贴一张画的很全面的图(来自https://juejin.im/post/6864175613209640973,侵删)。
# 1.1 DNS 域名解析
浏览器 DNS 缓存 -> 本地 hosts 文件 -> 本地 DNS 解析器缓存 -> 本地 DNS 服务器(具有权威性)-> 非本地 DNS 服务器区域有缓存(不具有权威性)-> 本地 DNS 服务器迭代查询(根、二级、三级...),查询到之后,先缓存再返回给客户机。
# 1.2 三次握手
发送端 SYN = 1, seq = x -> 接收端 SYN = 1, ACK = 1, seq = y, ack= x + 1 -> 发送端 ACK = 1, seq = x + 1, ack = y + 1。
为什么TCP客户端最后还要发送一次确认呢?
主要是为了防止已经失效的连接请求报文突然又传到服务器,产生错误和资源浪费。
# 1.3 发起 HTTP 请求
完整的 HTTP 请求包括起始行、请求头部、请求主体三部分。 请求方法有:
- GET:获取资源
- POST:传输实体主体
- PUT:传输文件
- DELETE:删除文件
- HEAD:获取报文首部
- OPTIONS:询问支持的方法
- TRACE:追踪路径
GET 和 POST 的区别:
- GET 请求没有 body,只有 url,请求数据放在 url 的 querystring 中;POST 请求的数据在 body 中,通常来自于表单提交。
- 所以,GET 请求对访问数据没有副作用,POST 有副作用,就好比数据库中的查询和更新。
- 因此,GET 可以被缓存,而 POST 不能缓存,也不能被收藏为书签。
# 1.4 接收 HTTP 响应
服务器受到浏览器发送的 HTTP 请求后,会将 HTTP 报文封装成 HTTP 的 Request 对象,并通过不同的 Web 服务器进行处理,处理完的结果以 HTTP 的 Response 对象返回,主要包括状态码,响应头和响应报文三部分。
⚠️ 注意,TCP 规定,
- SYN 报文段不能携带数据,但要消耗一个序号
- ACK 报文可以携带数据,但如果不携带数据则不消耗序号
- FIN 报文段可以携带数据,但即使不携带数据也要消耗一个序号。
为什么建立连接时三次握手而关闭连接要四次握手?
建立连接的时候,服务器在 LISTEN 状态下,收到建立连接请求的 SYN 的报文后,把 ACK 和 SYN 放在同一个报文段里发送给客户端。 而关闭连接的时候,服务器收到对方的 FIN 报文段,只是表示对方不再发送数据了但还能接收数据,此时服务器也未必已经发送完所有的数据了,因此服务器可以立即关闭,也可以发送完剩下的数据后再发送 FIN 报文段表示同意关闭连接,所以服务器的 ACK 和 FIN 一般都会分开发送,导致多了一次挥手。
如果已经建立了连接,但客户端故障了怎么办?
服务器设置了一个保活计时器来避免资源浪费,一般是 2 个小时,如果连接建立后一直没有收到客户端的数据,那么在保活计时器超时之后,服务器就会发送一个探测报文,以后每隔 75 分钟发送一个,若一连 10 个探测报文都没有回应,则服务器认为客户端故障,主动关闭连接。
# 1.5 浏览器解析渲染页面
- 构建文档对象模型(DOM)
- 构建 CSS 对象模型(CSSOM)
- 构建渲染树(Render Tree)
- 布局
- 绘制
# 1.6 关闭连接(四次挥手)
浏览器发完数据后,发送 FIN 请求断开连接 -> 服务器发送 ACK 表示同意 -> 服务器发送 FIN 请求断开连接 -> 浏览器发送 ACK 表示同意。
# 2. DNS 服务器
DNS 服务器分为三类:根 DNS 服务器,顶级域 DNS 服务器,权威 DNS 服务器。
DSN 查询有递归查询和迭代查询,其区别如下:
- 递归查询:必须返回一个准确的查询结果,如果该 DNS 服务器没有查到,那么就会成为代理去询问其他服务器。
- 迭代查询:DNS 服务器会像请求端返回其他能够解释查询的 DNS 服务器。
一般情况下,从请求主机到本地 DNS 服务器的查询是递归的,其余查询是迭代的。
# 3. TCP 与 UDP
# 3.1 优劣对比
TCP | UDP | |
---|---|---|
连接状态 | 面向连接 | 无连接 |
可靠性 | 可靠交付 | 尽最大努力交付 |
实时性 | 效率比 UDP 低 | 实时性好 |
收发方 | 点对点 | 一对一/多,多对一/多都可 |
系统资源需求 | 较高 | 较少 |
备注 | TCP 通过流量控制、序号、确认和定时器,确保正确、按序将数据从发送进程交付给接收进程 | 适用于对高速传输和实时性要求较高的通信或广播通信,且对数据安全性无特殊要求 |
# 3.2 TCP 发送方
超时重传,快重传。
快重传:在某报文段的定时器过期之前重传丢失的报文段。
# 3.3 TCP 接收方
累计确认,差错恢复。
虽然 TCP 是累计确认(类似 Go-Back-N,GBN 协议),但是它会缓存失序报文段,且允许接收方有选择地确认失序报文段,这就使得发送方可以选择重传(类似 Select-Repeat,SR 协议)。 因此,TCP 的差错恢复机制为 GBN 协议和 SR 协议的混合体。
# 3.4 TCP 流量控制与拥塞控制
都是对发送方的遏制。
流量控制是流量控制也是一个速率匹配服务,是为了避免接收方缓存溢出的。它其实是一个速率匹配服务,让发送方发送但未被确认的数据量小于接收方的接收窗口大小(rwnd 是动态变化的),就可以保证接收方缓存不会溢出。
拥塞控制是一个全局性的过程,为了避免过多数据注入到网络中,保证路由器或链路不过载的。拥塞的标志可以说是重传计时器超时或接收到三个重复确认。相关算法有慢启动算法、拥塞避免算法(使网络比较不容易拥塞而不是完全避免)、快重传、快恢复。
# 4. HTTP 协议
HTTP 协议包括两种报文:请求(Request)报文和响应(Response)报文,这里有很详细的解释。
https://juejin.im/post/6864175613209640973#heading-26
# 5. Cookie 和 Session
Cookie 和 Session 是用户识别和状态管理的机制,都是会话技术。
Cookie | Session | |
---|---|---|
运行 | 在客户端(浏览器) | 在服务器 |
限制 | 大小4K,且个数也有限制 | 与服务器内存相关 |
备注 | 有安全隐患,通过拦截或本地文件找到你的 Cookie 后可以进行攻击 | Session 保存在服务器上一段时间后才会消失,如果 Session 过多会增加服务器的压力 |
# 5.1 同域验证
由于 HTTP 是无状态的,一次请求结束,连接断开,下次服务器再收到请求,它就不知道这是哪个用户发过来的了,因而需要状态管理,以便服务器知道 HTTP 请求的发起者,从而判断该用户是否有权限继续这个请求,这个过程就是会话管理。
如果前端,后台 API 部署在同域下,登录方式相对简单,有以下两种:
- 基于 Session 登录:用 Cookie(在 HTTP header 中) 存储 Sessionid,在服务器 Session 中判断是否有登录凭证。
- 基于 Token 登录:用 Token(放到 URL 参数或 HTTP header 中) 去服务器解密并检查其内部的登录凭证是否有效。
# 5.2 跨域验证
浏览器具有同源策略,凡是发送请求的 URL、域名、端口号有一个与当前页面不同则视为跨域。
而浏览器不能跨域读取 Cookie 信息,因此,当客户端跨域访问时,浏览器不能读取先前跨域的服务器返回的 Cookie 信息,而服务器检测不到客户端请求里的会话信息,就判断客户端没有登录!
需要两步解决跨域问题:
- 解决同源问题:在服务器设置
Access-Control-Allow-Header
、Access-Control-Allow-Origin
为星号,若要发送 Cookie,则Origin
不能设置星号,需要设置为明确的、与客户端一致的域名。 - 请求带上 Cookie 信息:CORS 默认不发送 Cookie 和 HTTP 认证信息,因此服务器需要指定
Access-Control-Allow-Credentials: true
,另一方面需要在客户端的请求中添加withCredentials
属性。
# 6. HTTP
影响 HTTP 网络请求的因素主要有两个:带宽和延迟。
HTTP1.0 与 HTTP1.1 的区别(对缓断续错享长)
HTTP1.0 | HTTP1.1 | |
---|---|---|
缓存处理 | 强制缓存 | 对比缓存 |
带宽优化和网络连接的使用 | 需 Part 给 ALL | 支持断点续传 |
错误通知管理 | xx | 新增 24 个错误状态响应码 |
Host 头处理 | xx | 虚拟主机共享 IP |
长连接 | 每次请求都要三次握手 | 持久化连接和管线化处理 |
把添加了加密、认证机制、完整性保护的 HTTP 称为 HTTPS。
关于 HTTPS 的解释,个人认为这里讲的比较通俗。
# 7. WebSocket
HTML5 开始提供的一个全双工通信协议,建立连接时由客户端请求 HTTP 协议升级,握手成功后,使用 WebSocket 协议进行通信。
WebSocket 采用心跳来确保 TCP 通道保持连接没有断开(ping[0x9]、pong[0xA])。