【前端面试题】计算机网络相关

发布于:2025-03-27 ⋅ 阅读:(47) ⋅ 点赞:(0)

总结面试前端过程可能会问到的计算机网络相关知识点

1.HTTP和HTTPS的区别

(1)HTTPS = HTTP + 安全加密
HTTPS 是 HTTP 的 加密版,通过 SSL/TLS 保障数据安全,防止窃听和篡改。

(2)HTTPS 如何保护数据?

  • 加密传输:使用 TLS 协议对数据加密(如 AES、ChaCha20 算法),确保传输内容不可读。
  • 数据完整性:通过哈希算法(如 SHA-256)验证数据未被篡改。
  • 身份认证:服务器需提供由可信 CA(如 Let’s Encrypt)签发的数字证书,防止钓鱼网站。

(3)HTTP vs HTTPS 关键对比

对比维度 HTTP HTTPS
加密与安全性 明文传输,无加密 使用 SSL/TLS 加密,确保数据机密性和完整性
协议与端口 默认端口 80 默认端口 443
证书与身份验证 无证书要求 需 CA 签发数字证书,验证服务器身份
协议版本与 HTTPS 强制性 HTTP/1.1、HTTP/2 可明文传输 HTTP/3 强制使用 HTTPS;HTTP/2 默认需 HTTPS
浏览器行为与 SEO 标记为“不安全” 显示“安全”标识,提升 SEO 排名

2.HTTP1.0/1.1/2.0 的区别?

(1)HTTP1.0

HTTP 1.0 浏览器与服务器只保持短暂的连接,每次请求都需要与服务器建立一个TCP连接,服务器完成请求处理后立即断开TCP连接,服务器不跟踪每个客户也不记录过去的请求。简单来讲,每次与服务器交互,都需要新开一个连接。

如果需要建立长连接,需要设置一个非标准的Connection字段 Connection: keep-alive

(2)HTTP1.1

HTTP1.1中,默认支持长连接(Connection: keep-alive),即在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。

同时,HTTP 1.1还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,这样也显著地减少了整个下载过程所需要的时间。

同时,HTTP1.1HTTP1.0的基础上,增加更多的请求头和响应头来完善的功能,如下:

  • 引入了更多的缓存控制策略,如If-Unmodified-Since, If-Match, If-None-Match等缓存头来控制缓存策略
  • 引入range,允许值请求资源某个部分
  • 引入host,实现了在一台WEB服务器上可以在同一个IP地址和端口号上使用不同的主机名来创建多个虚拟WEB站点

并且还添加了其他的请求方法:putdeleteoptions

(3)HTTP2.0

在HTTP1.1基础上增加了以下特性:

  • 多路复用

    HTTP/2 复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了”队头堵塞”

  • 二进制分帧

    帧是HTTP2通信中最小单位信息

    每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装,这也是多路复用同时发送数据的实现条件。

  • 首部压缩

    HTTP/2在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键值对,对于相同的数据,不再通过每次请求和响应发送

    首部表在HTTP/2的连接存续期内始终存在,由客户端和服务器共同渐进地更新

  • 服务器推送

    HTTP2引入服务器推送,允许服务端推送资源给客户端

    服务器会顺便把一些客户端需要的资源一起推送到客户端,如在响应一个页面请求中,就可以随同页面的其它资源

3.OSI七层网络模型

OSI分层从上至下依次为应用层、表示层、会话层、传输层、网络层、数据链路层、物理层

(1)应用层

作用:通过应用程序间的交互来完成特定的网络应用
传输的数据流:报文
传输协议:DNS、HTTP、SMTP

(2)表示层

作用:使通信的应用程序能够解释交换数据的含义
该层提供的服务主要包括数据压缩,数据加密以及数据描述,使应用程序不必担心在各台计算机中表示和存储的内部格式差异

(3)会话层

作用:负责建立、管理和终止表示层实体之间的通信会话
该层提供了数据交换的定界和同步功能,包括了建立检查点和恢复方案的方法

(4)传输层

作用:为两台主机进程之间的通信提供服务,处理数据包错误、数据包次序,以及其他一些关键传输问题
传输的数据流:
传输协议:TCP、UDP

(5)网络层

作用:两台计算机之间传送数据时其通信链路往往不止一条,所传输的信息甚至可能经过很多通信子网,该层主要作用就是选择合适的网间路由和交换节点,确保数据按时成功传送
传输的数据流:包
传输协议:IP协议

(6)数据链路层

作用:在两个相邻节点之间传送数据时,数据链路层将网络层交下来的 IP数据报组装成帧,在两个相邻节点间的链路上传送帧
每一帧的数据可以分成:报头head和数据data两部分:

  • head 标明数据发送者、接受者、数据类型,如 MAC地址
  • data 存储了计算机之间交互的数据

传输的数据流:帧

(7)物理层

作用:实现计算机节点之间比特流的透明传送
传输的数据流:比特
该层主要是和硬件有关,与软件关系不大

4.DNS协议是什么?说说DNS 完整的查询过程?

DNS(Domain Names System),域名系统,是互联网一项服务,是进行域名和与之相对应的 IP 地址进行转换的服务器。

  • IP 地址:一长串能够唯一地标记网络上的计算机的数字
  • 域名:是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时对计算机的定位标识
(1)域名

域名是一个具有层次的结构,从上到下依次为根域名、顶级域名、二级域名、三级域名…
域名树
DNS 查询的方式有两种:

  • 递归查询:如果 A 请求 B,那么 B 作为请求的接收者一定要给 A 想要的答案
  • 迭代查询:如果接收者 B 没有请求者 A 所需要的准确内容,接收者 B 将告诉请求者 A,如何去获得这个内容,但是自己并不去发出请求

在域名服务器解析的时候,使用缓存保存域名和IP地址的映射

计算机中DNS的记录也分成了两种缓存方式:

  • 浏览器缓存:浏览器在获取网站域名的实际 IP 地址后会对其进行缓存,减少网络请求的损耗
  • 操作系统缓存:操作系统的缓存其实是用户自己配置的 hosts 文件
(2)查询过程

解析域名的过程如下:

  • 首先搜索浏览器的 DNS 缓存,缓存中维护一张域名与 IP 地址的对应表
  • 若没有命中,则继续搜索操作系统的 DNS 缓存
  • 若仍然没有命中,则操作系统将域名发送至本地域名服务器,本地域名服务器采用递归查询自己的 DNS 缓存,查找成功则返回结果
  • 若本地域名服务器的 DNS 缓存没有命中,则本地域名服务器向上级域名服务器进行迭代查询
    • 首先本地域名服务器向根域名服务器发起请求,根域名服务器返回顶级域名服务器的地址给本地服务器
    • 本地域名服务器拿到这个顶级域名服务器的地址后,就向其发起请求,获取权限域名服务器的地址
    • 本地域名服务器根据权限域名服务器的地址向其发起请求,最终得到该域名对应的 IP 地址
  • 本地域名服务器将得到的 IP 地址返回给操作系统,同时自己将 IP 地址缓存起来
  • 操作系统将 IP 地址返回给浏览器,同时自己也将 IP 地址缓存起
  • 至此,浏览器就得到了域名对应的 IP 地址,并将 IP 地址缓存起

域名查询过程

5.说说HTTP 常见的状态码有哪些,适用场景?

状态码第一位数字决定了不同的响应状态,有如下:

  • 1 表示消息
  • 2 表示成功 (200)
  • 3 表示重定向 (301)
  • 4 表示请求错误 (404)
  • 5 表示服务器错误 (500)
(1)1XX
  • 100(客户端继续发送请求,这是临时响应):这个临时响应是用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝。客户端应当继续发送请求的剩余部分,或者如果请求已经完成,忽略这个响应。服务器必须在请求完成后向客户端发送一个最终响应
  • 101:服务器根据客户端的请求切换协议,主要用于websocket或http2升级
(2)2XX
  • 200(成功):请求已成功,请求所希望的响应头或数据体将随此响应返回
  • 201(已创建):请求成功并且服务器创建了新的资源
  • 202(已创建):服务器已经接收请求,但尚未处理
  • 203(非授权信息):服务器已成功处理请求,但返回的信息可能来自另一来源
  • 204(无内容):服务器成功处理请求,但没有返回任何内容
  • 205(重置内容):服务器成功处理请求,但没有返回任何内容
  • 206(部分内容):服务器成功处理了部分请求
(3)3XX
  • 300(多种选择):针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择
  • 301(永久移动):请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置
  • 302(临时移动): 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求
  • 303(查看其他位置):请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码
  • 305 (使用代理): 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理
  • 307 (临时重定向): 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求
(4)4XX
  • 400(错误请求): 服务器不理解请求的语法
  • 401(未授权): 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
  • 403(禁止): 服务器拒绝请求
  • 404(未找到): 服务器找不到请求的网页
  • 405(方法禁用): 禁用请求中指定的方法
  • 406(不接受): 无法使用请求的内容特性响应请求的网页
  • 407(需要代理授权): 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理
  • 408(请求超时): 服务器等候请求时发生超时
(5)5XX
  • 500(服务器内部错误):服务器遇到错误,无法完成请求
  • 501(尚未实施):服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码
  • 502(错误网关): 服务器作为网关或代理,从上游服务器收到无效响应
  • 503(服务不可用): 服务器目前无法使用(由于超载或停机维护)
  • 504(网关超时): 服务器作为网关或代理,但是没有及时从上游服务器收到请求
  • 505(HTTP 版本不受支持): 服务器不支持请求中所用的 HTTP 协议版本

6.说说 HTTP 常见的请求头有哪些?以及作用?

字段名 说明 示例
Accept 能够接受的回应内容类型(Content-Types) Accept: text/plain
Accept-Charset 能够接受的字符集 Accept-Charset: utf-8
Accept-Encoding 能够接受的编码方式列表 Accept-Encoding: gzip, deflate
Accept-Language 能够接受的回应内容的自然语言列表 Accept-Language: en-US
Authorization 用于超文本传输协议的认证的认证信息 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control 用来指定在这次的请求/响应链中的所有缓存机制 都必须 遵守的指令 Cache-Control: no-cache
Connection 该浏览器想要优先使用的连接类型 Connection: keep-alive Connection: Upgrade
Cookie 服务器通过 Set- Cookie (下文详述)发送的一个 超文本传输协议Cookie Cookie: $Version=1; Skin=new;
Content-Length 以 八位字节数组 (8位的字节)表示的请求体的长度 Content-Length: 348
Content-Type 请求体的 多媒体类型 Content-Type: application/x-www-form-urlencoded
Date 发送该消息的日期和时间 Date: Tue, 15 Nov 1994 08:12:31 GMT
Expect 表明客户端要求服务器做出特定的行为 Expect: 100-continue
Host 服务器的域名(用于虚拟主机 ),以及服务器所监听的传输控制协议端口号 Host: en.wikipedia.org:80 Host: en.wikipedia.org
If-Match 仅当客户端提供的实体与服务器上对应的实体相匹配时,才进行对应的操作。主要作用时,用作像 PUT 这样的方法中,仅当从用户上次更新某个资源以来,该资源未被修改的情况下,才更新该资源 If-Match: “737060cd8c284d8af7ad3082f209582d”
If-Modified-Since 允许在对应的内容未被修改的情况下返回304未修改 If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
If-None-Match 允许在对应的内容未被修改的情况下返回304未修改 If-None-Match: “737060cd8c284d8af7ad3082f209582d”
If-Range 如果该实体未被修改过,则向我发送我所缺少的那一个或多个部分;否则,发送整个新的实体 If-Range: “737060cd8c284d8af7ad3082f209582d”
Range 仅请求某个实体的一部分 Range: bytes=500-999
User-Agent 浏览器的身份标识字符串 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/21.0
Origin 发起一个针对 跨来源资源共享 的请求 Origin: http://www.example-social-network.com

7.网络攻击及防范

(1)XSS攻击:

XSS (Cross Site Scripting) 跨站脚本攻击,允许攻击者将恶意代码植入到提供给其它用户使用的页面中

通过在用户输入的位置进行脚本的注入,可窃取用户cookie、劫持流量、插入广告、置入木马、获取用户信息等。

XSS的类型有:

  1. 反射型:浏览器将恶意代码提交到服务端,服务端将恶意代码返回给客户端。(像一个镜像反射过程)
  2. 储存型:浏览器将恶意代码提交到服务端,服务端将恶意代码存储到数据库。(危害最大)
  3. DOM型:恶意代码仅在客户端运行,不提交服务端。

防止XSS的方式:

对输入进行过滤,对输出进行转义。

  1. 对用户输入的内容进行格式校验(比如邮箱,手机号等信息)
  2. 过滤掉输入内容中的
(2)CSRF攻击:

CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求

一个典型的CSRF攻击有着如下的流程:

  • 受害者登录a.com,并保留了登录凭证(Cookie)
  • 攻击者引诱受害者访问了b.com
  • b.com 向 a.com 发送了一个请求:a.com/act=xx。浏览器会默认携带a.com的Cookie
  • a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求
  • a.com以受害者的名义执行了act=xx
  • 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作

防止csrf常用方案如下:

  • 阻止不明外域的访问
    • 同源检测
    • Samesite Cookie
  • 提交时要求附加本域才能获取的信息
    • CSRF Token
    • 双重Cookie验证

8.TCP和UDP的区别

(1)UDP

概念:UDP(User Datagram Protocol),用户数据包协议,是一个简单的面向数据报的通信协议,即对应用层交下来的报文,不合并,不拆分,只是在其上面加上首部后就交给了下面的网络层。也就是说无论应用层交给UDP多长的报文,它统统发送,一次发送一个报文。而对接收方,接到后直接去除首部,交给上面的应用层就完成任务。

特点如下:

  • UDP 不提供复杂的控制机制,利用 IP 提供面向无连接的通信服务
  • 传输途中出现丢包,UDP 也不负责重发
  • 当包的到达顺序出现乱序时,UDP 没有纠正 的功能。
  • 并且它是将应用程序发来的数据在收到的那一刻,立即按照原样发送到网络上的一种机制。即使是出现网络拥堵的情况,UDP 也无法进行流量控制等避免网络拥塞行为
(2)TCP

概念:TCP(Transmission Control Protocol),传输控制协议,是一种可靠、面向字节流的通信协议,把上面应用层交下来的数据看成无结构的字节流来发送。可以想象成流水形式的,发送方TCP会将数据放入“蓄水池”(缓存区),等到可以发送的时候就发送,不能发送就等着,TCP会根据当前网络的拥塞状态来确定每个报文段的大小。
特点如下:

  • TCP充分地实现了数据传输时各种控制功能,可以进行丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。而这些在 UDP 中都没有。
  • TCP 作为一种面向有连接的协议,只有在确认通信对端存在时才会发送数据,从而可以控制通信流量的浪费。
  • 根据 TCP 的这些机制,在 IP 这种无连接的网络上也能够实现高可靠性的通信( 主要通过检验和、序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现)
(3)两者的区别

两者区别如下表所示:

TCP UDP
可靠性 可靠 不可靠
连接性 面向连接 无连接
报文 面向字节流 面向报文
效率 传输效率低 传输效率高
双共性 全双工 一对一、一对多、多对一、多对多
流量控制 滑动窗口
拥塞控制 慢开始、拥塞避免、快重传、快恢复
传输效率
  • TCP 是面向连接的协议,建立连接3次握手、断开连接四次挥手,UDP是面向无连接,数据传输前后不建立连接,发送端只负责将数据发送到网络,接收端从消息队列读取

  • TCP 提供可靠的服务,传输过程采用流量控制、编号与确认、计时器等手段确保数据无差错,不丢失。UDP 则尽可能传递数据,但不保证传递交付给对方

  • TCP 面向字节流,将应用层报文看成一串无结构的字节流,分解为多个TCP报文段传输后,在目的站重新装配。UDP协议面向报文,不拆分应用层报文,只保留报文边界,一次发送一个报文,接收方去除报文首部后,原封不动将报文交给上层应用

  • TCP 只能点对点全双工通信。UDP 支持一对一、一对多、多对一和多对多的交互通信

应用层协议 应用 传输层协议
SMTP 电子邮件 TCP
SSH 远程终端接入 TCP
HTTP 万维网 TCP
FTP 文件传输 TCP
DNS 域名转换 UDP
TFTP 文件阐述 UDP
SNMP 网络管理 UDP

9.TCP三次握手和四次挥手

TCP(Transmission Control Protocol)是面向连接的协议,提供可靠的数据传输。
为了建立和断开连接,TCP 采用三次握手和四次挥手机制,确保双方状态同步,防止错误数据传输。

(1)三次握手

为什么是三次?
三次握手主要是为了防止旧的重复连接请求引起错误,同时确保通信双方的收发能力正常。

具体过程
假设 A(客户端)和 B(服务器)建立连接:

  1. A → B:发送 SYN(请求建立连接)
    • A 发送 SYN=1, seq=x,表示想要建立连接,并携带初始序列号 x。
  2. B → A:发送 SYN+ACK(确认请求)
    • B 收到 SYN 后,回复 SYN=1, ACK=1, seq=y, ack=x+1,表示接受连接,并发送自己的初始序列号 y,确认 A 的 x。
  3. A → B:发送 ACK(确认收到)
    • A 收到 B 的 SYN+ACK 后,发送 ACK=1, seq=x+1, ack=y+1,表示自己收到了 B 的确认。

关键点

  • 第 1 次:A 确保自己能发送数据。
  • 第 2 次:B 确保自己能收发数据(收到了 A 的 SYN)。
  • 第 3 次:A 确保自己能正确接收数据(收到了 B 的 SYN+ACK)。

为什么不能用两次握手?
如果只有两次握手,旧的 SYN 连接请求可能被服务器误认为是新连接,导致连接异常。因此,第三次握手是必要的,确保双方都确认对方的接收能力。

打个比方:
想象你在微信上给朋友发消息:“要不要出来吃饭?”

  • 由于网络延迟,这条消息很久之后才到朋友那里,但此时你已经不想吃饭了。
  • 如果朋友直接回复“好”(两次握手的情况),他可能会白跑一趟,因为你早就不去了。
  • 但如果朋友等你再确认一次(三次握手的 ACK),那么你可以告诉他:“别来了,我早就不去了。”
  • 这样朋友不会白跑一趟,避免了误会。
(2)四次挥手

为什么是四次?
TCP 连接是全双工通信,数据的发送和接收是独立的。
所以,断开连接需要双方各自确认自己的数据传输已完成,因此需要四次挥手。

具体过程
假设 A(客户端)主动关闭连接:

  1. A → B:发送 FIN(请求断开)
    • A 发送 FIN=1, seq=u,表示自己不再发送数据了,但仍可以接收数据。
  2. B → A:发送 ACK(确认请求)
    • B 收到 FIN 后,回复 ACK=1, seq=v, ack=u+1,表示收到了 A 的断开请求,但仍可能有数据要发送。
  3. B → A:发送 FIN(B 也关闭连接)
    • B 确保自己数据发送完毕后,发送 FIN=1, seq=w, ack=u+1,表示也不再发送数据了。
  4. A → B:发送 ACK(最终确认)
    • A 收到 FIN 后,回复 ACK=1, seq=u+1, ack=w+1,进入 TIME_WAIT 状态,等待一段时间(默认 2MSL),然后真正关闭连接。

关键点

  • 前两次挥手:A 先关闭发送通道,B 确认,但 B 还可以继续发送数据。
  • 后两次挥手:B 也关闭发送通道,A 最后确认后彻底断开连接。

为什么不能三次挥手?
如果 B 在ACK 和 FIN 一起发送,A 可能无法区分 B 只是确认了关闭,还是已经不再发送数据,容易导致数据丢失。因此,需要四次挥手,确保数据传输完整。

打个比方:
类比情侣分手,A发出离开请求,B还有话要说,B说完后再告诉A,A确认收到正式分手。

  • 第一次:A 说 “我不聊了”(FIN)
  • 第二次:B 说 “知道了,但我还有话说”(ACK)
  • 第三次:B 说 “好了,我说完了”(FIN)
  • 第四次:A 说 “OK,拜拜” + 等一会儿(ACK + TIME_WAIT)

10.强缓存和协商缓存

主要的区别在于HTTP请求头

(1)强缓存

原理:浏览器在本地缓存数据,在缓存有效期内 不会 向服务器发送请求,直接使用缓存文件。

关键 HTTP 头

  • Expires(HTTP/1.0):指定资源的过期时间(绝对时间),受本地时间影响较大。
  • Cache-Control(HTTP/1.1):常见取值:
    • max-age=3600(以秒为单位,表示资源可缓存 1 小时)
    • no-cache(仍需协商缓存)
    • no-store(不使用缓存,每次都请求服务器)

不会 发起请求,直接使用缓存,提高页面加载速度。

(2)协商缓存

原理:当强缓存失效后,浏览器会向服务器发送请求,并携带缓存标识,服务器通过该标识判断资源是否变更。

关键 HTTP 头

  • Last-Modified(HTTP/1.0) + If-Modified-Since
    • Last-Modified:文件最后修改时间,浏览器请求时带上 If-Modified-Since,服务器判断资源是否更新。
  • ETag(HTTP/1.1) + If-None-Match
    • ETag:资源的唯一标识符(哈希值或版本号),浏览器请求时带上 If-None-Match,服务器判断资源是否变化。

发送请求,但如果资源未变更,返回 304 Not Modified,浏览器复用缓存。加粗样式

11. 输入URL到加载页面具体发生了什么?

简单的分析,从输入 URL到回车后发生的行为如下:

  • URL解析
  • DNS 查询
  • TCP 连接
  • HTTP 请求
  • 响应请求
  • 页面渲染
(1)URL解析

判断输入的URL是否合法,一个合法的URL应该包含协议、域名、端口、路径、查询、锚点

(2)DNS查询

根据域名进行DNS的查询,包含递归和迭代查询方式,具体内容在第4题中

(3)TCP 连接

TCP三次握手建立链接四次挥手断开链接,具体内容再第9题中

(4)HTTP 请求

建立好TCP连接后就可以发起HTTP请求

  • 请求行 请求方法(post、get)请求URLHTTP协议和版本
  • 请求头 相关内容在第6题中
  • 请求主体
(5)响应请求
  • 状态行 请求结果
  • 响应头 响应类型,状态码内容在第5题中
  • 响应正文 返回数据
(6)页面渲染

当请求得到响应后,根据服务器返回的资源,进行资源解析:

  • 查看响应头的信息,根据不同的指示做对应处理,比如重定向,存储cookie,解压gzip,缓存资源等等
  • 查看响应头的 Content-Type的值,根据不同的资源类型采用不同的解析方式

关于页面的渲染过程如下:

  • 解析HTML,构建 DOM 树
  • 解析 CSS ,生成 CSS 规则树
  • 合并 DOM 树和 CSS 规则,生成 render 树
  • 布局 render 树( Layout / reflow ),负责各元素尺寸、位置的计算
  • 绘制 render 树( paint ),绘制页面像素信息
  • 浏览器会将各层的信息发送给 GPU,GPU 会将各层合成( composite ),显示在屏幕上

渲染流程如下图

12. 解决跨域问题

同源策略:

  • 协议相同(protocol)
  • 主机相同(host)
  • 端口相同(port)

如果不满足同源策略的网络请求就形成了跨域。

(1)解决方案之 jsonp:

利用

实现的前端代码:

showJsonp = function (obj) {
   console.log(obj)
}
// 回调函数拼在请求参数中
const url = 'http://localhost:3030/getTodoJsonp?callback=showJsonp'
// 利用script标签的src属性发起请求,解决跨域的问题,但仅限于get请求
const scriptEle = document.createElement('script')
scriptEle.setAttribute('src', url)
document.body.appendChild(scriptEle)
scriptEle.onload = function () {
   document.body.removeChild(scriptEle)
}

服务端代码(Node Express框架)

// 处理jsonp请求,解决跨域问题
app.get('/getTodoJsonp', function (req, res, next) {
  let callback = req.query.callback
  let content = callback + "({'message':'测试数据'})"
  res.send(content)
})

页面打印:{message: "测试数据"}

(2)解决方案之CORS:

CORS (Cross-Origin Resource Sharing,跨域资源共享)是一个系统,它由一系列传输的HTTP头组成,这些HTTP头决定浏览器是否阻止前端 JavaScript 代码获取跨域请求的响应

CORS 实现起来非常方便,只需要增加一些 HTTP 头,让服务器能声明允许的访问来源

只要后端实现了 CORS,就实现了跨域

后端代码栗子(Node Express框架)

// 设置允许跨域请求
app.all('*', function (req, res, next) {
  res.header('Access-Control-Allow-Origin', '*')
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
  res.header('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS')
  res.header('X-Powered-By', '3.2.1')
  res.header('Content-Type', 'application/json;charset=utf-8')
  next()
})

Access-Control-Allow-Origin 设置为*其实意义不大,可以说是形同虚设,实际应用中,上线前我们会将Access-Control-Allow-Origin 值设为我们目标host

(3)解决方案之Websocket:

Websocket 是 HTML5 的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。什么是全双工通信 ?简单来说,就是在建立连接之后,server 与 client 都能主动向对方发送或接收数据。我们这里以第三方库 ws 为例:

const WebSocket = require('ws');

const ws = new WebSocket('ws://www.host.com/path');

ws.on('open', function open() {
  ws.send('something');
});

ws.on('message', function incoming(data) {
  console.log(data);
});
... ...

需要注意的是,Websocket 属于长连接,在一个页面建立多个 Websocket 连接可能会导致性能问题。

(4)解决方案之Proxy:

代理(Proxy)也称网络代理,是一种特殊的网络服务,允许一个(一般为客户端)通过这个服务与另一个网络终端(一般为服务器)进行非直接的连接。一些网关、路由器等网络设备具备网络代理功能。一般认为代理服务有利于保障网络终端的隐私或安全,防止攻击

  1. vue项目开发过程可以配置vue.config.js文件来设置代理允许跨域。
// vue.config.js文件
module.exports = {
    devServer: {
        host: '127.0.0.1',
        port: 8080,
        open: true,// vue项目启动时自动打开浏览器
        proxy: {
            '/api': { // '/api'是代理标识,用于告诉node,url前面是/api的就是使用代理的
                target: "http://localhost:3030", //目标地址,一般是指后台服务器地址
                changeOrigin: true, //是否跨域
                pathRewrite: { // pathRewrite 的作用是把实际Request Url中的'/api'用""代替
                    '^/api': "" 
                }
            }
        }
    }
}

// axios发送请求中配置请求的根路径
axios.defaults.baseURL = '/api'
  1. 服务端实现代理请求转发

以express框架为例

var express = require('express');
const proxy = require('http-proxy-middleware')
const app = express()
app.use(express.static(__dirname + '/'))
app.use('/api', proxy({
  target: 'http://localhost:4000', 
  changeOrigin: false
}));
module.exports = app
  1. 通过配置nginx实现代理(一般用于生产环境中)
server {
		listen 8088;
		server_name 127.0.0.1; # 主机名
		gzip on;  # 开启gzip压缩功能
		gzip_min_length  1024; #设置最小压缩大小,单位字节
		gzip_types text/plain application/x-javascript text/css application/xml; #用来指定压缩的类型,“text/html”类型总是会被压缩。
		location / {
			root /home/exam/dist;
			index index.html index.htm;
			# 添加请求头
      add_header 'Access-Control-Allow-Origin' *;
      add_header 'Access-Control-Allow-Credentials' 'true';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
		}

		location /api {
			include uwsgi_params;
      # 代理请求路径
			proxy_pass http://127.0.0.1:3033/api;
		}

}

#前端面试题
#计算机网络


网站公告

今日签到

点亮在社区的每一天
去签到