# HTTP系列

# 1.1 什么是 HTTP

HTTP 是一个连接客户端,网关和服务器的一个协议。

# 1.2 特点

支持客户/服务器模式:可以连接客户端和服务器;

简单快速:请求只需传送请求方法,路径和请求主体;

灵活:传输数据类型灵活;

无连接:请求结束立即断开;

无状态:无法记住上一次请求。

# 1.3 怎么解决无状态和无连接

无状态:HTTP 协议本身无法解决这个状态,只有通过 cookie 和 session 将状态储存,常见的场景是登录状态保持;

无连接:可以通过自身属性 Keep-Alive。

# 1.4 从浏览器输入URL按回车到页面显示都发生了什么

  1. 浏览器根据URL进行DNS查询,找到 IP 地址

    • 首先从DNS缓存中查询
    • 若未在缓存中找到,则不停的向上一级级请求DNS服务器
  2. 根据IP地址,找到对应的服务器

  3. 建立TCP连接 (里面有个 三次握手)

  4. 连接建立后,发出HTTP请求

  5. 服务器根据请求作出HTTP响应

  6. 浏览器得到响应内容,进行解析与渲染,并显示

  7. 断开连接 (四次挥手)

以上整个过程叫一次HTTP事务

# 1.5 TCP 三次握手

所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个包,那么为什么在TCP建立连接时是三次握手,而不是两次或四次? TCP名为传输控制协议,是一种可靠的传输层协议。(原则上任何数据传输都无法确保绝对可靠,三次握手只是确保可靠的基本需要)

举个打电话的例子:

// 我: 喂,听得到吗?
// 对方:听得到,你能听的到我吗?
// 我:听得到耶,我们可以说话了
copy success
Copy successed

对应客户端与服务器之间的通信:

http8.1-1
  • 第一次握手 客户端A发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,服务器由SYN=1知道,A要求建立联机;
  • 第二次握手 服务器收到请求后要确认联机信息,向A发送ack number=(客户端A的 seq+1 ),syn=1,ack=1,随机产生seq=7654321的包;
  • 第三次握手 客户端A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,客户端A会再发送ack number=(服务器的seq+1),ack=1,服务器收到后确认seq值与ack=1则连接建立成功。

注:握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP连接都将被一直保持下去。

位码即tcp标志位,有6种标示:SYN(synchronous建立联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急)Sequence number(顺序号码) Acknowledge number(确认号码)

# 1.6 TCP 四次挥手

TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。

举个例子:

// 男:我们分手吧?
// 女:好,我同意

// 男: 你送我的礼物你拿走吧
// 女: 好,拜拜
copy success
Copy successed

对应客户端与服务器之间的通信:

http8.1-2

  • 第一次挥手

主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可以接受数据。

  • 第二次挥手

被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号, SYN 和 FIN 都有seq序号)。

  • 第三次挥手

被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。

  • 第四次挥手

主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手。

注:任何一方(客户端或服务器)都可以选择主动关闭,在双方还没有完全确定关闭连接时,还有可能存在没有发送完的数据

状态说明:

  • CLOSED: 这个表示初始状态。
  • LISTEN(服务器): 表示服务器端的某个SOCKET处于监听状态,可以接受连接了。
  • ESTABLISHED:表示连接已经建立了。
  • SOCKET:请自行百度

# 1.7 为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?

这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。

当关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。

# 1.8 HTTP1.1版本新特性

a. 默认持久连接节省通信量,只要客户端服务端任意一端没有明确提出断开TCP连接,就一直保持连接,可以发送多次HTTP请求 b. 管线化,客户端可以同时发出多个HTTP请求,而不用一个个等待响应 c. 断点续传,实际上就是利用HTTP消息头使用分块传输编码,将实体主体分块传输。

# 1.9 常见状态码

# 2开头(请求成功)表示成功处理了请求的状态代码。

200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。

201 (已创建) 请求成功并且服务器创建了新的资源。

202 (已接受) 服务器已接受请求,但尚未处理。

203 (非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。

204 (无内容) 服务器成功处理了请求,但没有返回任何内容。

205 (重置内容) 服务器成功处理了请求,但没有返回任何内容。

206 (部分内容) 服务器成功处理了部分 GET 请求。

# 3开头(请求被重定向)表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。

300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。

301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。

302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。

303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。

304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。

305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。

307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。

# 4开头(请求错误)这些状态代码表示请求可能出错,妨碍了服务器的处理。

400 (错误请求) 服务器不理解请求的语法。

401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。

403 (禁止) 服务器拒绝请求。

404 (未找到) 服务器找不到请求的网页。

405 (方法禁用) 禁用请求中指定的方法。

406 (不接受) 无法使用请求的内容特性响应请求的网页。

407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。

408 (请求超时) 服务器等候请求时发生超时。

409 (冲突) 服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。

410 (已删除) 如果请求的资源已永久删除,服务器就会返回此响应。

411 (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。

412 (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。

413 (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。

414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。

415 (不支持的媒体类型) 请求的格式不受请求页面的支持。

416 (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。

417 (未满足期望值) 服务器未满足"期望"请求标头字段的要求。

# 5开头(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。

500 (服务器内部错误) 服务器遇到错误,无法完成请求。

501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。

502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。

503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。

504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。

505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。

# 2.0 请求行、请求头、请求体

http8.1-3

请求行:1,2,3; 请求头:4; 请求体:5

# 2.1 缓存

分为强缓存和协商缓存:

**强缓存:**利用 cache-controlexpires 设置,直接返回一个过期时间,所以在缓存期间不请求,If-modify-since

**协商缓存:**响应头返回 etaglast-modified 的哈希值,第二次请求头 If-none-matchIF-modify-since 携带上次哈希值,一致则返回 304。

协商缓存对比: etag 优先级高于 last-modified

etag 精度高,last-modified 精度是 s,1s 内 etag 修改多少次都会被记录; last-modified 性能好,etag 要得到 hash 值。

**浏览器读取缓存流程:**会先判断强缓存;再判断协商缓存 etag(last-modified)是否存在;存在利用属性 If-None-match(If-Modified-since)携带值;请求服务器,服务器对比 etag(last-modified),生效返回 304。

F5 刷新会忽略强缓存不会忽略协商缓存,ctrl+f5 都失效

# 2.2 HTTP 2.0

  1. HTTP2.0的基本单位为二进制帧,采用二进制格式传输;
  2. 多路复用( 1次连接),其实就是将请求数据分成帧乱序发送到 TCP 中。TCP 只能有一个 steam,所以还是会阻塞;
  3. 报头压缩;
  4. 服务器推送主动向 B 端发送静态资源,避免往返延迟。
  5. HTTP2.0只适用于HTTPS的场景

# 2.3 HTTP 3.0

  1. 是基于 QUIC 协议,基于 UDP
  2. 特点:
  • 自定义连接机制:TCP 以 IP/端口标识,变化重新连接握手,UDP 是一 64 位 ID 标识,是无连接;
  • 自定义重传机制:TCP 使用序号和应答传输,QUIC 是使用递增序号传输; 无阻塞的多路复用:同一条 QUIC 可以创建多个 steam。

# 2.4 HTTPS

  1. https 是在 http 协议的基础上加了个 SSL;
  2. 主要包括:握手(凭证交换和验证)和记录协议(数据进行加密)。

# 2.5 随着 http2 的发展,前端性能优化中的哪些传统方案可以被替代

雪碧图、资源文件合并

# 2.6 http 1.1 中的 keep-alive 有什么作用

http 1.1 中,在响应头中设置 keep-alive 可以在一个 TCP 连接上发送多个 http 请求

  1. 避免了重开 TCP 连接的开销
  2. 避免了刷新时重新建立 SSL 连接的开销
  3. 避免了QPS过大时,服务器的连接数过大

在服务器端使用响应头开启 keep-alive:

Connection: Keep-Alive
Keep-Alive: timeout=5, max=1000
copy success
Copy successed

# 2.7 Cache-Control 和 Etag 的区别

用户操作 Expires/Cache-Control Last-Modified / Etag
地址栏回车 有效 有效
页面链接跳转 有效 有效
新开窗口 有效 有效
前进后退 有效 有效
F5刷新 无效 有效
Ctrl+F5强制刷新 无效 无效

# 2.8 XSS CSRF

XSS(跨站脚本攻击),恶意的注入html代码,其他用户访问时,会被执行

特点:

能注入恶意的HTML/JavaScript代码到用户浏览的网页上,从而达到Cookie资料窃取、会话劫持、钓鱼欺骗等攻击

防御手段:

  • 浏览器禁止页面的JS访问带有HttpOnly属性的Cookie
  • 两端进行输入格式检查
  • 通过编码转义的方式进行输出检查

# CSRF(攻击跨站请求伪造)

特点:

重要操作的所有参数都是可以被攻击者猜测到的。攻击者预测出URL的所有参数与参数值,才能成功地构造一个伪造的请求。

防御手段:

  • token验证机制,比如请求数据字段中添加一个token,响应请求时校验其有效性
  • 用户操作限制,比如验证码(繁琐,用户体验差)
  • 请求来源限制,比如限制HTTP Referer才能完成操作(防御效果相比较差)实践中常用第一种

# 2.9 负载均衡

多台服务器共同协作,不让其中某一台或几台超额工作,发挥服务器的最大作用

  1. http 重定向负载均衡:调度者根据策略选择服务器以302相应请求,缺点只有第一次有效果,后续操作维持在该服务器
  2. dns负载均衡:解析域名时,访问多个ip服务器中的一个(可监控性较弱)
  3. 反向代理负载均衡:访问统一的服务器,由服务器进行调度访问实际的某个服务器,对统一的服务器要求大,性能受到服务器群的数量影响

# 3.0 内存泄漏

定义:程序中己动态分配的堆内存由于某种原因程序未释放或无法释放引发的各种问题

js中可能出现的内存泄漏情况 结果:变慢,崩溃,延迟大等

原因:

  • 全局变量
  • dom清空时,还存在引用
  • ie中使用闭包
  • 定时器未清理
  • 子元素存在引起的内存泄露

避免策略:

  • 减少不必要的全局变量,或者生命周期较长的对象,及时对无用的数据进行垃圾回收;
  • 注意程序逻辑,避免“死循环”之类的 ;
  • 避免创建过多的对象 原则:不用了的东西要及时归还。
  • 减少层级过多的引用

点个Star支持我一下 ~