前端与网络

126 阅读15分钟

从历史悠久的一个问题开始本文~

地址栏输入url发生什么

  • 浏览器接收到URL,网络请求线程开启
  • 一个完整的H撒 TTP请求发出
    • DNS解析:浏览器自身DNS缓存 -> 搜索系统自身DNS缓存 -> 系统hosts文件查找 -> 本地域名服务器查询 -> 迭代的方式查询根域名服务器
    • TCP连接:三次握手、四次挥手
    • 发送HTTP请求
  • 服务器接收到请求并转到具体的处理后台
  • 前后台之间的HTTP交互和涉及的缓存机制
  • 浏览器接收到数据包后的关键渲染路径
    • 解析HTML和CSS文件,构建DOM和CSSOM
    • 将两个对象模型合并为渲染树
    • 从DOM树的根节点向下遍历子节点,忽略不可见的节点(脚本标记不可见、CSS隐藏不可见)
    • 在CSSOM中为每个可见的子节点找到对应的规则并应用
    • 根据得到的渲染树计算在视图中的具体位置和大小,输出的是“盒模型”
    • 绘制阶段,将每个节点的具体绘制方式转化为屏幕上的实际像素
  • JS引擎的解析

网络模型

OSI七层模型

  • 物理层
  • 数据链路层
  • 网络层
  • 传输层
  • 会话层
  • 表示层
  • 应用层

TCP/IP四层模型

  • 应用层:应用层、表示层、会话层:HTTP
  • 传输层:传输层:TCP/UDP
  • 网络层:网络层:IP
  • 数据链路层:数据链路层、物理层

TCP/UDP

  • tcp是基于连接的,可靠性高;udp是基于无连接的,可靠性较低
  • 由于tcp是连接的通信,需要有三次握手、重新确认等连接过程,会有延时,实时性差;由于协议所致,安全性较高;而udp无连接,无建立连接的过程,因而实时性较强,安全略差
  • 在传输相同大小的数据时,tcp首部开销20字节;udp首部开销只有8个字节,tcp报头比udp复杂,故实际包含的用户数据较少。tcp无丢包,而udp有丢包,故tcp开销大,udp开销较小
  • 每条tcp连接只能是点到点的;udp支持一对一、一对多、多对一、多对多的交互通信

三次握手、四次挥手

TCP协议基本操作

  • 发起连接:SYN(Synchroniation),请求同步
  • 断开请求:FIN(Finish),请求完成
  • 发送数据:PSH(Push),数据推送
  • 接收方收到数据后,都需要给发送方一个ACK(Acknowledgement)响应。请求/响应模型是可靠性的要求,如果一个请求没有响应,发送方会认为自己需要重发这个请求

三次握手过程

  • 第一次握手:客户端向服务器端发送序列号 seq=x 的标识,表示开始建立连接
  • 第二次握手:服务器端回发一个 ack=x+1 的标识,表示确认收到第一次握手,同时发送自己的标识 seq=y:客户端确认自己发出的数据能够被服务器端收到
  • 第三次握手:客户端发送 ack=y+1 的标识,标识确认收到第二次握手。服务器端确认自己发出的数据能够被客户端收到。 三次握手.gif

四次挥手过程

  • 客户端主动关闭,向服务器发FIN报文
  • 服务端接收后通知应用进程并向客户端发送ACK确认
  • 服务端处理完后被动关闭再次向客户端发送FIN以及ACK,进入LAST-ACK状态,
  • 客户端收到服务端发来的FIN后,发送 ACK 给服务端。在等待2MSL后进入CLOSED状态 四次挥手.gif

TCP为什么握手三次、挥手四次

  • TCP是一个双工协议,为了让双方都保证在建立连接的时候,连接双方都需要向对方发送SYC(同步请求)和ACK(响应)。
  • 握手阶段双方没有繁琐的工作,因此一方发出SYN后,另一方可以将自己的ACK和SYN打包为一条消息回复
  • 挥手阶段,双方都有可能有未完成的工作,收到挥手请求的一方,必须马上响应ACK,表示接收到挥手请求;最后等所有工作结束后,再发送请求中断连接FIN,因此4次挥手(不能合并中间两条消息)
  • 核心:握手阶段没有其他事情等待,所以可以将响应ACK和SYN打包一次发送;挥手阶段首先是必须马上响应ACK,其次是需要等所有请求都结束后,再中断连接

HTTP1,1.1,2,3的区别

  • HTTP/1.0 增加 HTTP 头,丰富传输资源类型,奠定互联网发展基础。
  • HTTP/1.1 增加持久连接、管线化、响应分块,提升了 HTTP 传输效率。
  • HTTP/2 采用二进制传输格式,通过 HTTP 多路复用、头部压缩、服务器端推送,将传输效率在 HTTP + TCP 架构上发挥到了极致。
  • HTTP/3 将传输层替换为 QUIC,通过改进的拥塞控制、流量控制、0-RTT 建连、传输层多路复用、连接迁移等特性,进一步提升了 HTTP 传输效率

HTTP1.0

  • 特点:
    • 请求端增加 HTTP 协议版本,响应端增加状态码。
    • 请求方法增加 POST、HEAD。
    • 请求端和响应端增加头部字段。
      • Content-Type 让响应数据不只限于超文本。
      • Expires、Last-Modified 缓存头。
      • Authorization 身份认证。
      • Connection: keep-alive 支持长连接,但非标准。
  • 痛点:
    • TCP 连接无法复用。
    • HTTP 队头阻塞,一个 HTTP 请求响应结束之后,才能发起下一个 HTTP 请求。
    • 一台服务器只能提供一个 HTTP 服务。

HTTP1.1

可以并行发起多个请求,并且也能复用同一个 TCP 连接,传输效率得到了提升。但响应端只能按照发送的顺序进行返回,为此很多浏览器会为每个域名至多打开 6 个连接,用增加队列的方式减少 HTTP 队头阻塞

  • 特点:
    • 持久连接:HTTP/1.1 默认开启持久连接,在 TCP 连接建立后不立即关闭,让多个 HTTP 请求得以复用。
    • 管线化技术:HTTP/1.1 中,多个 HTTP 请求不用排队发送,可以批量发送,这就解决了 HTTP 队头阻塞问题。但批量发送的 HTTP 请求,必须按照发送的顺序返回响应,相当于问题解决了一半,仍然不是最佳体验。
    • 支持响应分块:
      • HTTP/1.1 实现了流式渲染,响应端可以不用一次返回所有数据,可以将数据拆分成多个模块,产生一块数据,就发送一块数据,这样客户端就可以同步对数据进行处理,减少响应延迟,降低白屏时间。
      • Bigpipe 的实现就是基于这个特性,具体是通过定义 Transfer-Encoding 头来实现的。
    • 增加 Host 头:
      • HTTP/1.1 实现了虚拟主机技术,将一台服务器分成若干个主机,这样就可以在一台服务器上部署多个网站了。
      • 通过配置 Host 的域名和端口号,即可支持多个 HTTP 服务:Host: :
    • 增加 Cache-Control、E-Tag 缓存头。
    • 增加 PUT、PATCH、HEAD、 OPTIONS、DELETE 请求方法。
  • 痛点:HTTP 队头阻塞没有彻底解决,响应端必须按照 HTTP 的发送顺序进行返回,如果排序靠前的响应特别耗时,则会阻塞排序靠后的所有响应。

HTTP2

在 HTTP/2 中发送请求时,既不需要排队发送,也不需要排队返回,彻底解决了 HTTP 队头阻塞问题。对于头部信息,资源缓存等痛点也进行了优化。

  • 特点:
    • 请求优先级:多个 HTTP 请求同时发送时,会产生多个数据流,数据流中有一个优先级的标识,服务器端可以根据这个标识来决定响应的优先顺序。
    • 多路复用:TCP 传输时,不用按照 HTTP 的发送顺序进行响应,可以交错发送,接收端根据帧首部的标识符,就能找到对应的流,进而重新组合得到最终数据。
    • 服务器端推送:
      • HTTP/2 允许服务器未经请求,主动向客户端发送资源,并缓存到客户端中,以避免二次请求。
      • HTTP/1.1 中请求一个页面时,浏览器会先发送一个 HTTP 请求,然后得到响应的 HTML 内容并开始解析,如果发现有
    • 头部压缩:
      • HTTP/1.1 的头部字段包含大量信息,而且每次请求都得带上,占用了大量的字节。
      • HTTP/2.0 中通信双方各自缓存一份头部字段表,如:把 Content-Type:text/html 存入索引表中,后续如果要用到这个头,只需要发送对应的索引号就可以了。

HTTP3

  • 主要特点是对传输层进行了优化,使用 QUIC 替换 TCP,彻底规避了 TCP 传输的效率问题。
  • QUIC(Quick UDP Internet Connection)是基于 UDP 进行多路复用的传输协议。QUIC 没有连接的概念,不需要三次握手,在应用程序层面,实现了 TCP 的可靠性,TLS 的安全性和 HTTP2 的并发性。在设备支持层面,只需要客户端和服务端的应用程序支持 QUIC 协议即可,无操作系统和中间设备的限制
  • 特点:
    • 传输层连接更快:HTTP/3 基于 QUIC 协议,可以实现 0-RTT 建立连接,而 TCP 需要 3-RTT 才能建立连接
    • 传输层多路复用
    • 改进的拥塞控制
    • 优化的流量控制
    • 加密认证的报文
      • QUIC 中报文都是经过加密和认证的,在传输过程中保证了数据的安全。
      • TCP 头部没有经过任何加密和认证,在传输过程中很容易被中间网络设备篡改,注入和窃听。

HTTP缓存

强缓存

  • expires(1.0):控制缓存失效日期时间戳
    • 再次发起请求,比对expires和当前本地时间戳,小于的话说明未过期,直接读缓存
    • 对本地时间戳的过分依赖,如果客户端本地与服务器端时间不同步,或主动修改,对于缓存过期的判断无法达到预期
  • cache-control(1.1)
    • max-age:x :控制响应资源的有效期,以秒为单位的时间长度,表示资源在被请求到后的x秒内有效
    • no-cache:强制进行协商缓存; no-store:禁止使用任何缓存策略【互斥】
    • private:只能被浏览器缓存; public:浏览器缓存+代理服务器缓存【互斥】
    • s-maxage:缓存在代理服务器的过期时长,仅当设置public后生效
  • cache-control完美替代,expires仅为向下兼容

协商缓存

  • last-modified(1.0)
    • 流程:首次请求的响应头里包含此字段,属性值为该文件最近一次修改的时间戳;刷新后,请求头会携带if-modified-since,其值为上次响应头last-modified字段值;服务器收到该请求后,会比较当前资源的修改时间戳与if-modified-since的值,如果相同说明缓存未过期,否则重新请求新文件资源
    • 缺点:只是根据文件资源最后修改时间戳来判断,如果资源进行编辑但内容没有更新,也会更新时间戳,造成没必要的请求;因为时间戳单位为秒,如果在毫秒级时间内对文件进行了修改,是无法识别的
  • ETag(1.1)
    • 服务器为不同资源进行哈希运算所生成的字符串,类似文件指纹,文件内容编码不同,对应ETag值就不同,对资源修改由更精准的变化感知,因此ETag的优先级更高
    • 再次发起请求时,请求头字段为IF-None-Match
    • 若验证缓存有效,则Content-Length字段值为0
    • 生成ETag需要付出额外的计算开销,资源尺寸过大、数量较多、修改频繁,会影响服务器性能

缓存决策

  • 是否需要缓存(no-store【涉及用户敏感信息】)
  • 是否协商缓存(no-cache)
  • 是否可被代理服务器缓存(是public,否private)
  • 配置强制缓存过期时间max-age,配置协商缓存的ETag或last-modified
  • 不同类型文件做不同缓存策略(HTML no-store) 缓存决策.png

状态码

  • 1xx:表示目前是协议的中间状态,还需要后续请求
  • 2xx:表示请求成功
  • 3xx:表示重定向状态,需要重新请求
  • 4xx:表示请求报文错误
  • 5xx:服务器端错误

常用状态码:

  • 101 切换请求协议,从 HTTP 切换到 WebSocket
  • 200 请求成功,有响应体
  • 301 永久重定向:会缓存
  • 302 临时重定向:不会缓存
  • 304 协商缓存命中
  • 400 请求错误
  • 401 请求要求身份验证
  • 403 服务器禁止访问
  • 404 资源未找到
  • 405 禁用请求中指定的方法
  • 500 服务器端错误
  • 502 服务器作为网关或代理,从上游服务器收到无效响应(错误网关)
  • 503 服务器繁忙

OPTIONS请求方法及使用场景

  • OPTIONS方法是用于请求获得由Request-URI标识的资源在请求/响应的通信过程中可以使用的功能选项。通过这个方法,客户端可以在采取具体资源请求之前,决定对该资源采取何种必要措施,或者了解服务器的性能。该请求方法的响应不能缓存。
  • OPTIONS请求方法的主要用途有两个:获取服务器支持的所有HTTP请求方法;用来检查访问权限。
  • 例如:在进行 CORS 跨域资源共享时,对于复杂请求,就是使用 OPTIONS 方法发送嗅探请求,以判断是否有对指定资源的访问权限。

WebSocket

  • 基于tcp,可靠性传输协议,应用层协议
  • WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息;HTTP是单向的
  • WebSocket是需要浏览器和服务器握手进行建立连接的,而HTTP是浏览器发起向服务器的连接,服务器预先并不知道这个连接
  • WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的

跨域

同源策略

浏览器地址和请求地址的协议、域名、端口号需保持一致,否则,跨域,是浏览器的限制,且是在数据返回的时候判断是否同源,因为如果服务端在请求头开启了CORS,是不会拦截的。

解决方法

  • JSONP:利用<script>src属性不跨域的方式
  • CORS:响应头Access-Control-Allow-Origin配置相应白名单
  • 反向代理:利用其他服务转发,如dev阶段可用Node,prod阶段可用Nginx

正代反代

简言之:正代代理客户端,反代代理服务器

正向代理

类似跳板机,代理访问自己本身不能访问的资源,代理服务器拿到相应资源后,再返给客户端 正代.png

反向代理

  • 服务器根据客户端的请求,从其关系的一组或多组服务器上获取资源,然后再将这些资源返回给客户端,客户端只会得知代理服务器的IP地址,而不知道在代理服务器后面的服务器集群的存在。可能不同请求会被代理到不同服务器上
  • 作用
    1. 保证内网的安全,我们在用反代处理跨域时,可以看到访问的接口域名实际不是真正的接口域名,而且前端服务对应的地址
    2. 可做负载均衡,通过反向代理服务器来优化网站的负载

反代.png

网络安全

XSS (cross-site scripting)跨站脚本攻击

  • 攻击者添加代码嵌入到页面中,使用户访问时都会执行相应的嵌入代码
  • 解决方式:设置cookie时设http-only,js拿不到

CSRF(Cross Site Request Forgecy)跨站请求伪造

  • 过程
    • 用户登录站点A,本地记录了cookie
    • 没有登出站点A的情况下,登录了危险站点B,B要求访问A
    • 站点A没做csrf防御
      csrf.png
  • 特点:
    • CSRF(通常)发生在第三方域名。
    • CSRF攻击者不能获取到Cookie等信息,只是使用。
  • 防御
    • 使用Referer Header确定来源域名: 根据HTTP协议,在HTTP头中有一个字段叫Referer,记录了该HTTP请求的来源地址(https不发送referer)
    • 人机验证
    • CSRF_TOKEN:可以放在cookie中返回,但一定要设置http-only,请求时再同时携带token和csrf_token做鉴权;也可以在客户端随机生成一个csrf_token,发请求时再请求的body和cookie里同时加入,服务端验证这俩参数的一致性,否则就是伪造

请求劫持

  • DNS劫持:通过修改运营商的本地DNS记录;302跳转方式
  • HTTP劫持:向首部主体内容添加内容的攻击称为http响应截断攻击(%0D%0A%0D%0A表示两个换行,就把http首部和主体分隔开了)

总结

本文从老生常谈的一道面试题开始,到每个细节点的展开阐述,基本涉及到了前端需要了解的绝大部门关于计算机网络的内容,有些未涉及到的大家查漏补缺,职业生涯中碰到网络的问题和面试希望大家都可以迎刃而解~