HTTP知识总结

250 阅读11分钟

HTTP 变更历史

HTTP1.0

请求1:

建立TCP连接:三次握手 
浏览器发HTTP请求
服务器发HTTP响应 
断开TCP连接:四次挥手

请求2:

建立TCP连接:三次握手 
浏览器发HTTP请求 
服务器发HTTP响应 
断开TCP连接:四次挥手

HTTP 1.1

  • 连接可以复用:建立一次连接,发送多个请求和响应。(也是有限制数量的6-8个,有阻塞)
建立TCP连接:三次握手 
浏览器发HTTP请求a 
服务器发HTTP响应a 
浏览器发HTTP请求b 
浏览器发HTTP请求c 
服务器发HTTP响应b 
服务器发HTTP响应c
断开TCP连接:四次挥手
  • 也可以同时发送请求b,c,下一个请求不用等到上一个响应来了之后再发送
  • 缓存控制:用cache-control

HTTP 2.0

  • 多路复用:只需一个TCP连接,可以无限制处理多个请求,真正实现请求的并发。
  • 二进制分帧:将HTTP报文从字符串拆分为若干个最小的二进制帧组成,在另一端再重组形成一个完整的请求/响应,多个帧之间乱序发送,根据真头部的标识重新组装。
  • 压缩HTTP首部:请求/响应的首部太大了,压缩后再发送,避免浪费
  • 服务器推送:客户端可以获取服务器端推送的资源。

一、HTTP 缓存

HTTP的缓存分为缓存(强缓存)和内容协商(弱缓存)

缓存(强缓存)

强缓存是本地缓存,指浏览器不会发出请求,直接从本地缓存中读取。控制强缓存的两个字段:Expirescache-control

  • 在HTTP1.0时代,设置Expires,这是绝对时间,如果发送请求在Expires之前,缓存始终有效,不会去服务器请求。
  • 在HTTP1.1时代,使用cached-control:max-age = number,这是相对时间,如果在相对时间内,那么就不需要去服务端请求,直接从缓存中拿

内容协商(弱缓存)

协商缓存需要在服务器端对比资源是否修改,来判断是否可以使用缓存。若未改动,则返回304状态码,浏览器拿到此状态码就可以直接使用缓存数据了。否则服务器返回新资源。

控制协商缓存的两个字段是:Last-Modify/If-Modified-Since Etag/If-None-Match

Last-Modified:最后修改时间

当浏览器再次进行请求时,会向服务器传送 If-Modified-Since 报头,询问 Last-Modified 时间点之后资源是否被修改过。如果没有修改,则返回码为 304,使用缓存;如果修改过,则再次去服务器请求资源,返回码和首次请求相同为 200,资源为服务器最新资源。

ETag:

服务器根据实体内容生成一段 hash 字符串,标识资源的状态。浏览器会将这串字符串传回服务器,验证资源是否已经修改,如果没有修改,就返回304, 过程如下

image.png

二、HTTP 状态码

  • 2xx 表示成功
  • 3xx 表示需要进一步操作
  • 4xx 表示浏览器方面出错
  • 5xx 表示服务器方面出错
状态码英文释义中文解释
100Continue临时响应
200Ok请求成功
301Moved Permanently永久重定向
302Found临时重定向
304Not Modified资源未更改过。缓存机制里有
400Bad Request请求参数错误
403Forbidden请求身份错误,禁止访问
404Not Found请求失败,找不到网页
405Method Not Allowed请求方法错误
500Internal Server Error服务器遇到未知错误
502Bad Gateway从上游服务器遇到无效响应

三、HTTP 和 HTTPS 的区别有哪些?

  • HTTP(hypertext transfer protocol)超文本传输协议
  • HTTPS(secure hypertext transfer protocol)安全文本传输协议
  • HTTPS = HTTP + SSL / TLS(安全层)
HTTPHTTPs
中文释义超文本传输协议安全文本传输协议
安全性明文传输,不安全加密传输,安全
端口号80443
速度较快较慢
是否需要证书不需要需要 免费/购买

HTTPS原理以及握手阶段

四、HTTP报文

分为请求报文、响应报文

请求报文(四部分组成)

  • 请求行,请求方法字段 URL字段 HTTP协议版本,如 GET /data/info.html HTTP/1.1
  • 请求报头:AcceptCache-ControlCookieConnection等字段
  • 空行
  • 请求数据:若方法字段是GET,则此项为空,没有数据;若方法字段是POST,则通常来说此处放置的就是要提交的数据
POST /auth/login HTTP/1.1    //当前HTTP版本
Host: blog-server.hunger-valley.com
Connection: keep-alive       //长链接
Content-Length: 41           //数据长度41
Accept: application/json, text/plain,         //希望是json的格式
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2Vybm
User-Agent: Mozilla/5.0 
Content-Type: application/json;charset=UTF-8   //内容是json格式,utf-8
Origin: https://xulei1998.github.io            //请求源
Referer: https://xulei1998.github.io/
Accept-Encoding: gzip, deflate, br             //压缩方式
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
{"username":"hunger","password":"123456"}

响应报文(四部分组成)

  • 响应行:HTTP协议版本 状态码及其描述,如 HTTP/1.1 200 OK
  • 响应报头:ServerConnectionExpiresLast-Modified
  • 空行
  • 响应报文:如果请求的是HTML/CSS/JS,那么返回的就是HTML/CSS/JS代码。
HTTP/1.1 200 OK                            //状态码
Server: nginx/1.4.6 (Ubuntu)               //服务器
Date: Wed, 20 Jan 2021 07:28:09 GMT        //时间
Content-Type: application/json; charset=utf-8  
Content-Length: 406                        //内容长度
Connection: keep-alive
X-Powered-By: Express
Access-Control-Allow-Origin: *             //访问控制允许源
Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
ETag: W/"196-Ay8U/71Rt0EbDzvYIuK2YtXe7xE"
{"status":"ok","msg":"登录成功","data":{"id":1,"username":"hunger","avatar":"https://avatars.dicebear.com/api/human/hunger.svg?mood[]=happy","createdAt":"2020-09-17T03:03:55.803Z","updatedAt":"2020-09-17T03:03:55.803Z"},"token":"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2Vybm"}

五、应用层协议 VS 传输层协议

  • 应用层 HTTP 考虑接收到数据的内容格式,不考虑是否这次传输可达
  • 传输层 TCP 只保证这次传输是可靠的,不关注后续的传输数据内容,UDP 不保证传输的可靠性

OSI 七层模型

  1. 物理层
  2. 数据链路层
  3. 网络层
  4. 传输层 TCP / UDP
  5. 表示层
  6. 会话层
  7. 应用层 HTTP

TCP/IP 四层模型

  1. 网络接口层
  2. 网络层
  3. 传输层
  4. 应用层

image.png

六、TCP协议

TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层协议。与之同层的是UDP(用户数据报协议),是不可靠的传输层协议。(HTTP是应用层协议)

目的:让网络传输更加可靠

TCP报文格式

image.png

在TCP报文段的TCP首部,有三个值得注意的字段:

  • ACK:应答报文0/1,TCP协议规定,只有ACK=1时有效,也就是连接建立后所有发送的报文的ACK必须为1。

  • SYN:请求报文, 在连接建立时用来同步序号。SYN=1就表示这是一个连接请求或连接接受报文。

    • 当SYN=1,ACK=0时,表明这是一个连接请求报文(询问)
    • 对方若同意建立连接,则应在响应报文(应答) 中使SYN=1和ACK=1。
  • FIN:释放请求报文,当 FIN = 1 时,表明此报文段的发送方的数据已经发送完毕,想要关闭连接。

结合 序号seq 和 确认号ack 去理解:

  • 询问报文:[ACK=0,SYN=1, seq=123] 询问号是123
  • 应答+询问报文:[ACK=1,SYN=1, seq=234, ack=124] 对seq为123的报文进行应答。询问下一个报文,询问号是234
  • 应答报文:[ACK=1, SYN=0, seq=124, ack=235] 对seq为234的报文进行应答

三次握手——建立TCP连接

可以想象成两人用对讲机在交谈。

A:Are you ok? (SYN=1,seq=100 )询问

B:I am fine. And you? (ACK=1, ack=101. SYN=1, seq=200) 应答+询问

A:Me too. (ACK=1, ack=201) 应答

image.png 客户端向服务器端发送数据之前,需要建立连接,经历三次握手:

  1. 客户端发送 SYN=1的询问报文给服务器端,seq是x,进入 SYN_SENT 状态(请求已发送)。
  2. 服务器端收到报文,回应一个ACK=1、SYN=1 的应答+询问报文。应答号ack是x+1,询问号seq是y,进入 SYN_RCVD 状态(请求已接收)。
  3. 客户端收到询问后,回应一个 ACK=1的应答报文,应答号是y+1,进入 Established 状态(建立连接)。

为什么要三次握手?而不是两次?

假设只有两次握手:客户端—>发送请求—>服务器端。服务器端—>返回应答—>客户端

  • 数据重传:客户端发送请求报文A,因网络延时服务器端没收到。客户端又发了一遍报文A,服务器收到后应答,建立链接等待客户端发送数据。客户端正常发送数据。 过了一会第一次因网络延迟发送的报文A也到达服务器,服务器再次应答,建立链接等待客户端发送数据,而客户端因已经接收过应答而不再传送数据,服务器端会一直处于“建立好连接,等待传数据的阶段”会浪费大量的服务器资源。
  • 而三次握手就会避免这种情况的发生:客户端会在收到应答+询问之后,返回一个应答,这样即使第一次的报文A发送到服务器,服务器也已经知道自己的应答+询问已经被客户端接收,从而不再继续等待,节省了资源。

四次挥手——释放TCP连接

image.png

  1. 客户端发送一个 FIN 报文,告诉服务器想关闭连接。
  2. 服务器收到这个 FIN ,先发回一个 ACK报文,说我收到了。
  3. 服务器发送一个 FIN 给客户端,我也想关闭连接。(服务器通知应用程序关闭网络连接,应用程序关闭后通知服务器。)
  4. 客户端发回 ACK 报文确认。

为什么挥手要四步?而不是2 3合并?

2 3步骤里的ACK报文和FIN报文需要分开发送,因为中间服务器端还可能向客户端发送数据,客户端已经想关闭连接,不再发送数据,但还可以接收数据。


从输入URL到看到页面发生了什么?

  • DNS解析域名
  • 发起TCP连接(三次握手)
  • 发送HTTP请求(请求体,请求报头,请求正文)
  • 服务器处理请求并返回HTTP报文(状态码,响应报头,响应报文)
  • 断开tcp连接(四次挥手)
  • 浏览器解析、渲染页面

1 DNS解析域名

输入www.google.com网址后,首先在本地的域名服务器中查找,没找到去域名服务器.去查找,没有再去.com顶级域名服务器查找,如此的类推下去,直到找到IP地址,然后把它记录在本地,供下次使用。大致过程就是.-> .com ->google.com. -> www.google.com.

2 发起TCP连接(三次握手)

三次握手的过程

3 发送HTTP请求(浏览器->服务器)

请求报文的组成:请求行(GET和POST区别)、请求头、请求正文

HTTP缓存(在):强缓存、协商缓存

4 服务器处理请求并返回HTTP报文(服务器->浏览器)

状态码

5 断开tcp连接(四次挥手)

6 浏览器解析渲染页面

  • 解析HTML形成DOM树
  • 解析CSS形成CSSOM 树
  • 合并DOM树和CSSOM树形成render tree渲染树
  • 浏览器开始渲染布局
  • 并绘制页面

回流:当Render Tree中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。

  • 页面首次渲染
  • 浏览器窗口大小发生改变
  • 元素尺寸、位置、内容、字体大小变化、添加或者删除可见的DOM元素
  • 查询某些属性或调用某些方法

重绘:当页面中元素color、background color的改变并不影响它在文档流中的位置时。

优化

CSS
  • 尽可能在DOM树的最末端改变class。
  • 避免设置多层内联样式。
  • 动画元素使用绝对定位可以减小reflow,使它脱离文档流(浏览器只会计算这个元素本身位置的变化,小范围计算)
JavaScript
  • 避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。
  • 避免频繁操作DOM,DOM离线后修改。(对虚拟DOM不断修改,再一次性渲染到真实DOM上)

参考阅读