前端面试常见问题——HTTP篇
2021-01-05 本文已影响0人
Marvel_Dreamer
1. HTTP状态码
-
1XX:信息状态码:接收的请求正在处理
-
100 Continue
继续,一般在发送post
请求时,已发送了http header
之后服务端返回此信息表示确认,之后发送具体参数信息
-
-
2XX:成功状态码:请求正常处理完毕
-
200 OK
正常返回信息 -
201 Created
请求成功并且服务器创建了新的资源 -
202 Accepted
服务器已接受请求,但尚未处理 -
204 No Content
服务器接收的请求已成功处理,但返回的响应报文中不含实体的主体部分 -
206 Partical
Content 客户端进行了范围请求,服务器成功执行了这部分GET请求,响应报文中包含由Content-Range指定范围的实体内容
-
-
3XX:重定向状态码:需要进行附加操作以完成请求
-
301 Moved Permanently
请求的网页已永久移动到新位置,以后应使用资源现在所指的URI -
302 Found
临时性重定向,希望本次能使用新的URI访问 -
303 See Other
临时性重定向,且总是使用GET
请求新的URI
-
304 Not Modified
自从上次请求后,请求的网页未修改过 -
307 Temporary Redirect
与302有相同含义,但不会从POST变成GET
-
-
4XX:客户端错误状态码:服务器无法处理请求
-
400 Bad Request
服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求 -
401 Unauthorized
第一次返回表示需要认证,第二次返回表示认证失败 -
403 Forbidden
禁止访问 -
404 Not Found
找不到如何与URI
相匹配的资源
-
-
5XX: 服务器错误状态码:服务器处理请求出错
-
500 Internal Server Error
服务器执行请求时发生错误 -
503 Service Unavailable
服务器端暂时无法处理请求(可能是过载或维护)
-
2. HTTP请求方法
-
GET
请求访问服务器上的某一资源 -
POST
向指定资源提交数据进行处理请求,数据被包含在请求体中 -
PUT
向服务器提交数据并保存到请求URI指定的位置,传输文件 -
HEAD
只请求页面的首部,不返回报文主体部分 -
DELETE
删除指定的资源 -
OPTIONS
查询针对请求URI指定资源所支持的方法 -
TRACE
让web服务器端将之前的 请求通信环回给客户端的方法 -
CONNECT
要求通信时建立隧道,实现用隧道协议进行TCP通信
3. HTTP请求报文结构
- 首行是Request-Line包括:请求方法,请求URI,协议版本,CRLF
- 首行之后是若干行请求头,包括通用头部,请求头部,实体头部,每个一行以CRLF结束
- 请求头和消息实体之间有一个CRLF分隔
- 根据实际请求需要可能包含一个消息实体 一个请求报文例子如下
HTTP请求报文结构.png
4. HTTP响应报文结构
- 首行是状态行包括:HTTP版本,状态码,状态描述,后面跟一个CRLF
- 首行之后是若干行响应头,包括:通用头部,响应头部,实体头部
- 响应头部和响应实体之间用一个CRLF分隔
- 最后是一个可能的消息实体 响应报文例子如下:
HTTP响应报文结构.png
5. HTTP1.0 与 HTTP1.1区别
-
长连接
-
HTTP/1.0
默认使用短连接,每次请求都要重新建立连接。开销会比较大。HTTP 1.1
起,默认使用长连接 ,默认开启Connection:keep-alive
。 可以用长连接来发多个请求。 - 有非流水线和流水线方式。流水线方式是客户在收到HTTP的响应报文之前就能接着发送新的请求报文。与之相对应的非流水线方式是客户在收到前一个响应后才能发送下一个请求
-
-
错误状态响应码
- 在
HTTP1.1
中新增了24个错误状态响应码,如410(Gone)表示服务器上的某个资源被永久性的删除。
- 在
-
缓存处理
-
HTTP1.0
主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准 -
HTTP1.1
则引入了更多的缓存控制策略例如Entity tag
,If-None-Match
等更多可供选择的缓存头来控制缓存策略。
-
-
带宽优化
-
HTTP1.0
中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能 -
HTTP1.1
允许只请求资源的某个部分,返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接
-
6. Http2.0
-
多路复用
- 在
HTTP/1
中,为了性能考虑,我们会引入雪碧图、使用多个域名等等的方式。这一切都是因为浏览器限制了同一个域名下的请求数量,当页面中需要请求很多资源的时候,队头阻塞会导致在达到最大请求数量时,剩余的资源需要等待其他资源请求完成后才能发起请求 - 在
HTTP/2
中引入了多路复用技术,可以只通过一个 TCP 连接就可以传输所有的请求数据。解决了浏览器限制同一个域名下的请求数量的问题,也更容易实现全速传输,新开一个 TCP 连接需要慢慢提升传输速度 - 在
HTTP/2
中,有两个非常重要的概念,分别是帧(frame)
和流(stream)
-
帧代表着最小的数据单位
,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流
-
多路复用
,就是在一个 TCP 连接中可以存在多条流。也就是可以发送多个请求,对端可以通过帧中的标识知道属于哪个请求。通过这个技术,可以避免 HTTP 旧版本中的队头阻塞问题,极大的提高传输性能
- 在
-
Header 压缩
- 在
HTTP/1
中,我们使用文本的形式传输 header,在 header 携带 cookie 的情况下,可能每次都需要重复传输几百到几千的字节。 - 在
HTTP/2
中,传输的 header 进行编码,减少了 header 的大小。并在两端维护了索引表,用于记录出现过的 header ,后面在传输过程中就可以传输已经记录过的 header 的键名,对端收到数据后就可以通过键名找到对应的值。
- 在
-
服务端 Push
- 在
HTTP/2
中,服务端可以在客户端某个请求后,主动推送其他资源。可以想象以下情况,某些资源客户端是一定会请求的,这时就可以采取服务端 push 的技术,提前给客户端推送必要的资源,这样就可以相对减少一点延迟时间
- 在
7. HTTP/3
-
HTTP/2存在的问题
-
HTTP/2
使用多路复用,同一域名下只需要使用一个TCP
连接。当连接中出现了丢包的情况,整个TCP
都要开始等待重传,也就导致了后面的所有数据都被阻塞,表现情况反倒不如HTTP/1
。对于HTTP/1
来说,开启多个TCP
连接,出现这种情况只会影响其中一个连接,剩余的还可以正常传输数据。 - 这个问题是底层支撑的
TCP
协议的问题。那么就会有人考虑到去修改TCP
协议,但这已经是一件不可能完成的任务了。因为TCP
存在的时间太长,已经充斥在各种设备中,并且这个协议是由操作系统实现的,更新起来不大现实。 - 基于这个原因,Google 就更起炉灶搞了一个基于
UDP
协议的QUIC
协议,并且使用在了HTTP/3
上,HTTP/3
最大的改造就是使用了QUIC
。
-
-
QUIC:
-
QUIC
基于UDP
,但是在原本的基础上新增了多路复用、0-RTT、使用 TLS1.3 加密、流量控制、有序交付、重传等等功能。
-
-
多路复用
- 虽然
HTTP/2
支持了多路复用,但是TCP
协议终究是没有这个功能的。QUIC
原生就实现了这个功能,并且传输的单个数据流可以保证有序交付且不会影响其他的数据流。 -
QUIC
在移动端的表现也会比TCP
好。因为TCP
是基于IP
和端口
去识别连接的,这种方式在多变的移动端网络环境下是很脆弱的。但是QUIC
通过ID
的方式去识别一个连接,不管网络环境如何变化,只要 ID 不变,就能迅速重连。
- 虽然
-
0-RTT
- 对于
TCP
连接需要1RTT,对于HTTPS
这种应用而言,由于还需要额外的TLS
握手,需要3RTT。而QUIC
可以做到0RTT,即通信双方发起通信连接时,第一个数据包便可以携带有效的业务数据 - 如果一对使用
QUIC
进行加密通信的双方此前从来没有通信过,那么0RTT是不可能的,如果客户机与服务器彼此之间曾经建立TLS连接,则可以使用从该会话缓存的信息来建立新的TLS连接,而不必从头协商,即第一次连接断开后,缓存当前会话的上下文,在下次恢复会话的时候,只需要将之前的缓存传递给服务端验证通过就可以进行传输了。
- 对于
-
纠错机制
- 假如说这次我要发送三个包,那么协议会算出这三个包的异或值并单独发出一个校验包,也就是总共发出四个包。当出现其中的非校验包丢包的情况时,可以通过另外三个包计算出丢失的数据包的内容。当然这种技术只能使用在丢失一个包的情况下,如果出现丢失多个包就不能使用纠错机制了,只能使用重传的方式。
8. HTTPS
-
HTTP的不足
- 通信使用明文(不加密),内容可能会被窃听;
- 不验证通信方的身份,有可能遭遇伪装;
- 无法证明报文的完整性,有可能已遭篡改;
-
HTTP +加密+认证+完整性保护=HTTPS
-
HTTPS
是安全版的HTTP
,不是一个新的协议,而是HTTP
加上加密处理、认证以及完整性保护。通信接口部分先和SSL
通信,再由SSL
和TCP
通信。所谓HTTPS
,其实就是身披SSL
协议这层外壳的HTTP
。
-
-
HTTPS采用混合加密机制
-
共享密钥加密
:加密和解密同用一个密钥的方式称为共享密钥加密,也叫做对称密钥加密,以共享密钥加密时必须将密钥也发送给对方,但如何安全转交密钥则称为一大困难。 -
公开密钥加密
:公开密钥加密方式很好地解决了共享密钥加密的困难。公开密钥加密使用一对非对称的密钥,一把私有密钥,一把公开密钥。其中公开密钥任何人都可以获得。发送密文方使用公开密钥进行加密处理,接收方使用私钥进行解密,而根据公开密钥和密文进行解密是异常困难的。 -
HTTPS
采用混合加密机制
:在交换密钥阶段使用公开密钥加密方式,建立通信交换报文阶段使用共享密钥加密方式,既保证共享密钥不被窃取,同时也不会因为公开密钥过于复杂的加密方式导致效率过低。
-
-
证明公开密钥正确性的证书
- 非对称密钥加密方式的问题在于,无法证明公开密钥是否被攻击者调包。为了解决这个问题,可以使用由数字证书认证机构和其相关机关颁发的公开密钥证书
- 数字证书认证机构在判明提出申请者的身份之后,会对已申请的公开密钥做数字签名,将该公开密钥放入公钥证书后绑定在一起。服务器会将这份由数字证书认证机构颁发的公钥证书发送给客户端,接到证书的客户端可使用数字证书认证机构的公开密钥,对那张证书上的数字签名进行验证,一旦验证通过,客户端便可明确:一,认证服务器的公开密钥的是真实有效的数字证书认证机构。二,服务器的公开密钥是值得信赖的。
-
完整性保护
- 应用层发送数据时附加MAC报文摘要,可以查知报文是否被篡改从而保护报文完整性
-
HTTPS通信步骤
- 简单来说,客户端向一个需要
HTTPS
访问的网站发起请求,服务器将证书(包含公钥)发给客户端进行校验,客户端校验成功后,会给服务器发送一个使用公钥加密后的随机串,服务器使用私钥解密这个串,从此服务器与客户端使用这个随机串进行对称加密通信。
- 简单来说,客户端向一个需要
9. TCP
- 建立连接断开连接都需要先需要进行握手。在传输数据的过程中,通过各种算法保证数据的可靠性,当然带来的问题就是相比 UDP 来说不那么的高效
- 三次握手与四次挥手
-
ARQ协议
- 即超时重传机制,通过确认和超时机制保证了数据的正确送达,ARQ 协议包含
停止等待ARQ
和连续ARQ
两种协议。 -
停止等待ARQ
:只要发送一段报文,都要停止发送并启动一个定时器,等待对端回应,在定时器时间内接收到对端应答就取消定时器并发送下一段报文。若出现丢包超时或输过程中报文出错,就会再次发送数据直到对端响应,所以需要每次都备份发送的数据。 -
连续ARQ
:在连续 ARQ 中,发送端拥有一个发送窗口,可以在没有收到应答的情况下持续发送窗口内的数据,通过累计确认,可以在收到多个报文以后统一回复一个应答报文,告诉发送端这个序号之前的数据已经全部接收到了,相比停止等待 ARQ 协议来说减少了等待时间,提高了效率,弊端在于可能造成重复发送数据的情况(7号已经正确接收而6号丢失)
- 即超时重传机制,通过确认和超时机制保证了数据的正确送达,ARQ 协议包含
-
流量控制
- 在
TCP
中,两端其实都维护着窗口
:分别为发送端窗口和接收端窗口。 - 发送端窗口包含已发送但未收到应答的数据和可以发送但是未发送的数据
- 发送端窗口是由接收窗口剩余大小决定的。接收方会把当前接收窗口的剩余大小写入应答报文,发送端收到应答后根据该值和当前网络拥塞情况设置发送窗口的大小,所以发送窗口的大小是不断变化的。
- 实现了流量控制的功能
- 出现零窗口情况时,发送端会停止发送数据,并定时发送请求给对端,让对端告知窗口大小。在重试次数超过一定次数后,可能会中断
TCP
链接
- 在
-
拥塞处理
-
慢启动
:连接开始时,最初cwnd
(拥塞窗口)=1 MSS(最大报文长度),每过一个RTT,发送速率翻倍,起始慢,慢启动阶段指数增长,直到:- 出现超时指示的丢包事件,将
cwnd
设为1并重新开始慢启动,将ssthresh
(慢启动阈值)设为ssthresh/2 -
cwnd
等于ssthresh
时结束慢启动转移至拥塞避免模式 - 检测到三个冗余
ACK
进行快速重传并进入快速恢复状态
- 出现超时指示的丢包事件,将
-
拥塞避免
:每个RTT只增加1个MSS- 出现超时,
cwnd
设为1个MSS,ssthresh
更新为cwnd/2 - 出现三个冗余
ACK
时,cwnd
减半,ssthresh
更新为cwnd/2,进入快速恢复状态
- 出现超时,
-
快速恢复
- 对引起进入快速恢复的缺失报文段,对收到的每个冗余
ACK
,cwnd
增加1个MSS,最终当对丢失报文段的一个ACK
到达时,降低cwnd
后进入拥塞避免状态 - 如果出现超时,
cwnd
设为1并ssthresh
更新为cwnd
的一半,迁移到慢启动状态
- 对引起进入快速恢复的缺失报文段,对收到的每个冗余
-
10. UDP
-
UDP
协议是面向无连接的,不需要在正式传递数据之前先建立连接,不对数据报文进行拆分和拼接操作,不保证有序且不丢失的传递到对端,没有任何控制流量的算法,在网络条件不好的情况下可能会导致丢包,头部开销小,提供了单播,多播,广播的功能,适合实时性要求高的应用场景(如直播,电话会议等) - 总的来说
UDP
相较于TCP
更加的轻便
11. 三次握手与四次挥手
标志位介绍-
三次握手
- 第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入
SYN_SENT
状态,等待服务器确认; - 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入
SYN_RECV
状态; - 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入
ESTABLISHED
(TCP连接成功)状态,完成三次握手。
- 第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入
-
四次挥手
- 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,此时,客户端进入
FIN-WAIT-1
(终止等待1)状态。 - 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,服务端进入关闭等待状态。这时客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个
CLOSE-WAIT
状态持续的时间。 - 客户端收到服务器的确认请求后,客户端进入
FIN-WAIT-2
(终止等待2)状态,等待服务器发送连接释放报文。 - 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,服务器进入了
LAST-ACK
(最后确认)状态,等待客户端的确认。 - 客户端收到服务器的连接释放报文后,必须发出确认,客户端就进入了
TIME-WAIT
(时间等待)状态。注意此时TCP连接还没有释放,必须经过2MSL(最长报文段寿命)的时间后,才进入CLOSED
状态。 - 服务器只要收到了客户端发出的确认,立即进入
CLOSED
状态,结束了这次的TCP连接。服务器结束TCP连接的时间要比客户端早。
- 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,此时,客户端进入
-
【问题1】为什么连接三次握手,关闭却是四次握手?
- 因为建立时当Server端收到Client端连接请求报文后,可以直接发送确认报文。但是关闭连接时Server端收到FIN报文时,很可能并不会立即关闭,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。等到Server端所有的报文都发送完了,才能发送FIN报文,因此不能一起发送。故需要四步握手。
-
【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
- 在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2个最大报文段生存时间。如果在该时间内再次收到FIN,那么Client会重发并重新计时。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。
-
【问题3】为什么不能用两次握手进行连接?
- 主要为了防止已失效的请求连接报文忽然又传送到了,从而产生错误。
- 假定A向B发送一个连接请求,由于一些原因,导致A发出的连接请求在一个网络节点逗留了较长时间。此时A会将此连接请求作为无效处理,重新向B发起了一次新的连接请求,B正常收到此连接请求后建立了连接,数据传输完成后释放了连接。如果此时A发出的第一次请求又到达了B,B会以为A又发起了一次连接请求,如果是两次握手:此时连接就建立了,B会一直等待A发送数据,从而白白浪费B的资源。 如果是三次握手:由于A没有发起连接请求,也就不会理会B的连接响应,B没有收到A的确认连接,就会关闭掉本次连接。
-
【问题4】如果已经建立了连接,但是客户端突然出现故障了怎么办?
- TCP还设有一个保活计时器,每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若2小时内还没有收到客户端的任何数据,服务器会发送探测报文段,以后每隔75秒钟发送一次。若一连发送10个仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。