GET 和 POST 请求的区别(重点)
GET 和 POST 是 HTTP 请求的两种方法,其区别如下:
(1)应用场景
GET 请求是一个幂等的请求,一般 GET 请求用于对服务器资源不会产生影响的场景,比如请求网页资源。
POST不是一个幂等的请求,一般用于对服务器资源会产生影响的情景,比如注册用户。
幂等性:意味着,无论你执行多少次相同的操作,结果都是一样的。重复发送同一个 GET 请求,不会对服务器资源状态产生任何改变,每次返回的结果都应该相同。GET、PUT、DELETE 请求都有幂等性。
GET 请求应该是幂等的,实际幂等性取决于服务器实现。
(2)是否缓存
因为两者应用场景不同,浏览器一般会对 GET 请求缓存,但很少对 POST 请求缓存。
(3)发送的报文格式
GET 请求的报文中实体部分为空,POST 请求的报文中实体部分一般为向服务器发送的数据。
(4)安全性
GET 请求可以将请求的参数放入 URL 中向服务器发送,这样的做法相对于 POST 请求来说是不太安全的,因为请求的 URL 会被保留在历史记录中。
(5)请求长度
浏览器由于对 URL 长度的限制,所以会影响 GET 请求发送数据时的长度。这个限制是浏览器规定的,并不是 RFC 规定的。
RFC:Request for Comments(请求意见稿),是互联网的官方标准,定义互联网上的核心功能,包括 HTTP、TCP、TLS 等技术。
(6)参数类型
POST 的参数传递支持更多的数据类型。
常见的 HTTP 请求头和响应头(重点)
HTTP 常见的请求头
| 请求头 | 说明 |
|---|---|
| Accept | 告知服务器客户端可接受的响应内容类型,支持权重 q 表示优先级 |
| Accept-Charset | 声明客户端支持的字符编码(在现代 HTTP/1.1 实践中几乎被忽略,因为 UTF-8 已基本成为统一编码,且服务端通常通过 Content-Type 中的 charset 参数指定编码) |
| Accept-Encoding | 支持的内容压缩算法,服务器可选择其一压缩响应 |
| Accept-Language | 客户端偏好的自然语言,用于服务器返回对应语言的内容 |
| Connection | 控制连接行为,keep-alive 表示希望复用 TCP 连接 |
| Cookie | 携带之前服务器通过 Set-Cookie 存储的状态信息,用于维持会话 |
| Host | 指定请求的目标主机名和端口号(HTTP/1.1 必需) |
| Referer | 指示当前请求的来源页面 URL,用于防盗链、统计等 |
| User-Agent | 标识客户端软件信息,帮助服务器适配不同设备 |
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Charset: utf-8, iso-8859-1;q=0.5
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: keep-alive
Cookie: sessionId=abc123; theme=dark
Host: www.example.com
Referer: https://www.google.com/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/144.0.0.0
Safari/537.36
Edg/144.0.0.0
HTTP 常见的响应头
| 响应头 | 说明 |
|---|---|
| Date | 表示响应生成的日期和时间(GMT 时区) |
| Server | 服务器软件的名称和版本 |
| Connection | 控制连接是否在请求完成后继续保持,keep-alive 则复用当前 TCP 连接减少握手开销,close 则响应后立即关闭连接 |
| Cache-Control | 指示缓存策略,决定资源如何被浏览器或中间缓存(CDN、代理)存储和重用 |
| Content-Type | 表示响应体的 MIME 类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型,一种用于标识文件或数据格式的标准化标签)及字符编码 |
Date: Mon, 26 Jan 2026 15:00:40 GMT
Server: nginx/1.24.0
Connection: keep-alive
Cache-Control: max-age=3600, public
Content-Type: application/json; charset=utf-8
Content-Type 常见的四种属性值
| 属性值 | 说明 |
|---|---|
| application/x-www-form-urlencoded | 浏览器的原生 form 表单,如果 form 标签不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。该种方式提交的数据放在 body 里面,数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码 |
| multipart/form-data | 一个常见的 POST 提交方式,通常在表单上传文件时使用 |
| application/json | 服务器消息主体是序列化后的 JSON 字符串 |
| text/xml | 该种方式主要用来提交 XML 格式的数据 |
<form action="/submit" method="post">
<input type="text" id="username" name="username" value="张三">
<button type="submit">提交</button>
</form>
为什么请求头和响应头都有 Connection?
-
请求中的 Connection:客户端向服务器表明自己的连接偏好。即使 HTTP/1.1 默认长连接,很多客户端仍会主动带上
Connection: keep-alive,以保证对 HTTP/1.0(默认每次请求后关闭 TCP 连接)的兼容性。 -
响应中的 Connection:服务器可以覆盖客户端的偏好。例如,如果服务器压力大或已知客户端即将断开,可能会在响应中返回
Connection: close来通知客户端关闭连接。 -
Connection 直接影响了 HTTP 的性能——是否复用连接。 在网络请求中,合理使用长连接可以减少延迟和资源消耗,因此这个头部几乎出现在每个 HTTP 请求和响应中。
HTTP 状态码 304 的利弊分析(重点)
服务器为了提高网站访问速度,对之前访问的部分页面指定缓存机制,当客户端在此对这些页面进行请求,服务器会根据缓存内容判断页面与之前是否相同,若相同便直接返回 304,此时客户端调用缓存内容,不必进行二次下载。
状态码 304 不应该认为是一种错误,而是对客户端有缓存的情况下,服务端的一种响应。
搜索引擎会更加青睐内容源更新频繁的网站,它通过特定时间内对网站抓取返回的状态码来调节对该网站的抓取频次。若网站在一定时间内一直处于 304 的状态,那么可能会降低对网站的抓取次数。相反,若网站变化频率非常快,每次抓取都能获取新内容,那么回访率也会提高。
搜索引擎对 304 的处理策略未公开,以上内容基于一般性推测。
产生较多 304 状态码的原因
- 页面更新周期长或不更新
- 纯静态页面或强制生成静态 HTML
强制生成静态 HTML:指的是网站通过技术手段,在服务器上预先生成完整的、纯粹的 HTML 文件,而不是在用户每次请求时都动态地查询数据库、运行程序来实时拼接页面。它是一种性能优化策略,适配了浏览器的缓存机制,使得大量重复访问可以直接读取本地缓存来满足,大幅提升用户访问速度,显著降低服务器负载和带宽消耗。
304 状态码出现过多会造成的问题
- 网站快照停止
- 收录减少
- 权重下降
常见的 HTTP 请求方法(重点)
| 方法 | 说明 |
|---|---|
| GET | 向服务器获取数据 |
| POST | 将实体提交到指定的资源,通常会造成服务器资源的修改 |
| PUT | 上传文件,更新数据 |
| DELETE | 删除服务器上的对象 |
| HEAD | 获取报文首部,与 GET 相比,不返回报文主体部分 |
| OPTIONS | 询问支持的请求方法,用来跨域请求 |
| CONNECT | 要求在与代理服务器通信时建立隧道,使用隧道进行 TCP 通信 |
| TRACE | 回显服务器收到的请求,主要用于测试或诊断 |
CONNECT 方法
工作原理:
- 客户端向代理服务器发送 CONNECT 请求。
- 代理服务器与目标服务器建立 TCP 连接。
- 代理服务器转发双方的数据,不做任何处理(隧道模式)。
使用场景:常用于代理服务器、VPN 等网络工具。
- HTTPS 代理:通过 HTTP 代理访问 HTTPS 网站
- 其他协议代理:通过代理访问其他协议(如 WebSocket)
TRACE 方法
工作原理:
- 客户端发送 TRACE 请求。
- 服务器将接收到的请求原样返回作为响应体。
- 客户端可以查看请求在传输过程中是否被修改。
使用场景:主要用于调试,生产环境通常禁用。
- 调试代理链:检查中间代理是否修改了请求
- 跨站跟踪检测:发现是否存在 XST(跨站跟踪)攻击(TRACE 可能返回包含 Cookie 的请求,结合 XSS 可能窃取用户凭证)
OPTIONS 请求方法的功能及使用场景(重点)
OPTIONS 是一种 HTTP 请求方法。
通过这个方法,客户端可以在采取具体资源请求之前,决定对该资源采取何种必要措施,或者了解服务器的性能。
该请求方法的响应不能缓存。
OPTIONS 请求方法的两个主要用途
- 获取服务器支持的所有 HTTP 请求方法。
- 用来检查访问权限。
例如,在进行 CORS 跨域资源共享时,对于复杂请求,就是使用 OPTIONS 方法发送嗅探请求,以判断是否有对指定资源的访问权限。
HTTP/1.0 和 HTTP/1.1 之间的区别(重点)
连接方面
HTTP/1.0 默认使用非短连接,而 HTTP/1.1 默认使用长连接。
HTTP/1.1 通过使用长连接来使多个 HTTP 请求复用同一个 TCP 连接,以此来避免使用短连接时每次需要建立连接的时延。
资源请求方面
在 HTTP/1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能。
HTTP/1.1 则在请求头引入了 Range 头域,它允许只请求资源的某个部分,即返回码是 206(Partial Content),方便了开发者自由选择以便于充分利用带宽和连接。
Range 头主要在以下情况出现:大文件下载(多线程下载器)、媒体文件流式传输(视频/音频的跳转/定位操作)、断点续传功能。普通网页浏览时通常看不到这个字段,因为浏览器一次性请求完整资源,如果要测试观察,可以使用大文件下载或视频播放的场景。
缓存方面
HTTP/1.0 中主要使用响应头里的 Expires、 Last-Modified(配合请求头里的 If-Modified-Since) 来做为缓存判断的标准。
HTTP/1.1 则引入了更多的缓存控制策略,例如 Cache-Control、Etag(配合请求头里的 If-None-Match)、If-Unmodified-Since、If-Match 等更多可供选择的缓存头来控制缓存策略。
| 缓存类型 | 优先级 |
|---|---|
| 强缓存 | 优先 Cache-Control,次之 Expires |
| 协商缓存 | 优先 If-None-Match(配合 Etag),次之 If-Modified-Since |
If-Unmodified-Since:乐观锁机制,防止并发更新时的数据覆盖,常用于协同编辑文章。
If-Match:确保客户端正在操作的是其认为的版本,防止覆盖其他客户端的更新。
字段方面
HTTP/1.1 中新增了 Host 字段,用来指定服务器的域名。
HTTP/1.0 中认为每台服务器都绑定一个唯一的 IP 地址,因此,请求消息中的 URL 并没有传递主机名。
但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机,并且它们共享一个 IP 地址,因此有了 Host 字段,这样就可以将请求发往到同一台服务器上的不同网站。
请求方法方面
HTTP/1.1 相对于 HTTP/1.0 还新增了很多请求方法,如 PUT、HEAD、OPTIONS 等。
HTTP/1.1 和 HTTP/2 的区别(重点)
二进制协议
HTTP/2 是一个二进制协议。
在 HTTP/1.1 版中,报文的头信息必须是文本(ASCII 编码),数据体可以是文本,也可以是二进制。
HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,统称为 “帧”,可以分为头信息帧和数据帧。帧的概念是 HTTP/2 实现多路复用的基础。
多路复用
HTTP/2 实现了多路复用,它仍然复用 TCP 连接,但是在一个连接里,客户端和服务器都可以同时发送多个请求或回应,而且不用按照顺序发送,这样就避免了“队头堵塞”的问题。
队头堵塞:是由 HTTP 基本的“请求 - 应答”模型所导致的。HTTP 规定报文必须是“一发一收”,这就形成了一个先进先出的“串行”队列。队列里的请求是没有优先级的,只有入队的先后顺序,排在最前面的请求会被最优先处理。如果队首的请求因为处理得太慢耽误了时间,那么队列里后面的所有请求也不得不跟着一起等待,结果就是其他的请求承担了不应有的时间成本,造成了“队头堵塞“的现象。
数据流
HTTP/2 使用了数据流的概念,因为 HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的请求。因此,必须要对数据包做标记,指出它属于哪个请求。
HTTP/2 将每个请求或回应的所有数据包称为一个数据流。 每个数据流都有一个独一无二的编号,数据包发送时,都必须标记数据流 ID,用来区分它属于哪个数据流。
头信息压缩
HTTP/2 实现了头信息压缩。
由于 HTTP/1.1 协议不带状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,比如 Cookie 和 User Agent,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。
HTTP/2 对这一点做了优化,引入了专门的 HPACK 压缩机制:
- 一方面,HPACK 使用哈夫曼编码对头部字段值进行压缩,减少传输字节数。
- 另一方面,客户端和服务器共同维护一个静态表(预定义常见头部)和动态表(连接过程中更新的自定义头部)。所有字段都会存入这个表,并生成一个索引号,以后就不发送同样字段了,只发送索引号,从而大大提高速度。
服务器推送
HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送。 使用服务器推送提前给客户端推送必要的资源,可以减少一些延迟时间。
这里需要注意的是 HTTP/2 下服务器主动推送的是静态资源,和 WebSocket 以及使用 SSE 等方式向客户端发送即时数据的推送是不同的。
HTTP 和 HTTPS 协议的区别(重点)
| 对比项 | HTTP | HTTPS |
|---|---|---|
| 传输方式 | 明文传输 | 具有安全性的 SSL 加密传输 |
| 端口 | 80 | 443 |
| 安全性 | 连接简单,无状态 | 可进行加密传输、身份认证,更加安全 |
| 证书 | 不需要 | 需要 CA 证书,费用较高 |
在浏览器中输入网址并且按下回车之后的处理流程(重点)
解析 URL
首先会对 URL 进行解析,分析它使用的传输协议和请求的资源的路径。
如果输入的 URL 中的协议或者主机名不合法,将会把地址栏中输入的内容传递给搜索引擎。
如果没有问题,浏览器会检查 URL 中是否出现了非法字符,如果存在非法字符,则对非法字符进行转义后再进行下一过程。
缓存判断
浏览器会判断所请求的资源是否在缓存里,如果请求的资源在缓存里并且没有失效,那么就直接使用,否则向服务器发起新的请求。
DNS 解析
首先需要获取的是输入的 URL 中的域名的 IP 地址,会先判断本地是否有该域名的 IP 地址的缓存,如果有则使用,如果没有则向本地 DNS 服务器发起请求。
本地 DNS 服务器也会先检查是否存在缓存,如果没有就会先向根域名服务器发起请求,获得负责的顶级域名服务器的地址后,再向顶级域名服务器请求,然后获得负责的权威域名服务器的地址后,再向权威域名服务器发起请求,最终获得域名的 IP 地址后,本地 DNS 服务器再将这个 IP 地址返回给请求的用户。
用户向本地 DNS 服务器发起请求属于递归请求。
本地 DNS 服务器向各级域名服务器发起请求属于迭代请求。
获取 MAC 地址
当浏览器得到 IP 地址后,数据传输还需要知道目的主机 MAC 地址,因为:
- 应用层下发数据给传输层,TCP 协议会指定源端口号和目的端口号,然后下发给网络层。
- 网络层会将本机地址作为源地址,获取的 IP 地址作为目的地址,然后将下发给数据链路层。
- 数据链路层的发送需要加入通信双方的 MAC 地址。
在数据链路层里,本机的 MAC 地址作为源 MAC 地址,对于目的 MAC 地址,通过将目的 IP 地址与本机的子网掩码相与,可以判断是否与请求主机在同一个子网里,然后分情况处理:
- 如果在同一个子网里,可以使用 ARP 协议获取到目的主机的 MAC 地址。
- 如果不在一个子网里,那么请求转发给网关,由它代为转发,此时同样可以通过 ARP 协议来获取网关的 MAC 地址,此时目的主机的 MAC 地址应该为网关的地址。
TCP 三次握手
TCP 建立连接的三次握手的过程:
- 首先,客户端向服务器发送一个 SYN 连接请求报文段和一个随机序号,服务端接收到请求后向客户端发送一个 SYN ACK 报文段和一个随机序号,确认连接请求。
- 客户端接收服务器的确认应答后,进入连接建立状态,同时向服务器也发送一个 ACK 确认报文段。
- 服务器端接收到确认后,也进入连接建立状态,此时双方的连接就建立起来了。
HTTPS 握手
如果使用的是 HTTPS 协议且 TLS 版本为 1.2,则通信前还存在 TLS 的四次握手过程。
TLS 就是 HTTPS 中那个代表 “S,安全”的部分,全称是传输层安全协议,SSL 是 TLS 的前身,现在常说的 SSL 指代的其实就是 TLS,TLS 是 SSL 的标准化和升级版,SSL 3.0 之后的版本就改名叫 TLS 1.0/1.2/1.3 了。
TLS 四次握手的过程:
- 首先,由客户端向服务器端发送使用的协议的版本号、一个随机数和可以使用的加密方法。
- 服务器端收到后,确认加密的方法,也向客户端发送一个随机数和自己的数字证书。
- 客户端收到后,首先检查数字证书是否有效。如果有效,则再生成一个随机数并使用证书中的公钥对随机数加密、一个前面所有内容的 hash 值供服务器端检验,然后发送给服务器端。
- 服务器端接收后,使用自己的私钥对数据解密,同时向客户端发送一个前面所有内容的 hash 值供客户端检验。这个时候双方都有了三个随机数,按照之前所约定的加密方法,使用这三个随机数生成一把秘钥,以后双方通信前,就使用这个秘钥对数据进行加密后再传输。
返回数据
当页面请求发送到服务器端后,服务器端会返回一个 HTML 文件作为响应。
浏览器接收到响应后,开始对 HTML 文件进行解析,开始页面的渲染过程。
页面渲染
浏览器首先会根据 HTML 文件构建 DOM 树,根据解析到的 CSS 文件构建 CSSOM 树,如果遇到 script 标签,则判断是否含有 defer 或者 async 属性,没有则直接加载和执行 script,造成页面渲染的阻塞。
当 DOM 树和 CSSOM 树建立好后,根据它们来构建渲染树。
渲染树构建好后,会根据渲染树来进行布局。
布局完成后,最后使用浏览器的 UI 接口对页面进行绘制。这个时候整个页面就显示出来了。
TCP 四次挥手
最后一步,是 TCP 断开连接的四次挥手过程。
- 若客户端认为数据发送完成,则它需要向服务端发送连接释放请求(FIN 包)。
- 服务端收到客户端的连接释放请求后,会发送确认应答(ACK 包),并进入 CLOSE_WAIT 状态。此时,服务端内核会通知应用层对方已关闭连接。注意,从这一刻起,客户端到服务端的单方向数据传输已经结束,服务端不再接收来自客户端的数据(因为客户端已不会主动发送),但 TCP 连接是双向的,服务端仍可以继续向客户端发送尚未发完的数据。待服务端应用层处理完剩余数据并主动调用关闭后,服务端再向客户端发送连接释放请求(FIN 包),随后进入 LAST-ACK 状态,等待客户端对这次 FIN 的最终确认。
- 客户端收到释放请求后,向服务端发送确认应答(ACK 包),进入 TIME-WAIT 状态,该状态会持续 2MSL(Maximum Segment Lifetime,报文段最大生存时间,指报文段在网络中生存的时间,超时会被抛弃)时间,若该时间段内没有服务端的重发请求(指的是服务端因未收到最后一次 ACK 而重传的 FIN 报文),就进入 CLOSED 状态。
- 当服务端收到确认应答后,也进入 CLOSED 状态。
对 Keep-Alive 的理解(重点)
-
HTTP/1.0 中默认是在每次请求/应答,客户端和服务器都要新建一个连接,完成之后立即断开连接,这就是短连接。
-
当使用 Keep-Alive 模式时,Keep-Alive 功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive 功能避免了重新建立连接,使得一次 TCP 连接上可以发送多个 HTTP 请求/响应,这就是长连接。
Keep-Alive 的使用方法
-
HTTP/1.0 版本默认使用短连接。 要想进行长连接,必须手动配置发送
Connection: keep-alive。若想断开 Keep-Alive 连接,需发送Connection: close。 -
HTTP/1.1 规定了默认保持长连接。 数据传输完成了保持 TCP 连接不断开,等待在同域名下继续用这个通道传输数据。如果需要关闭,需要客户端发送
Connection: close。
Keep-Alive 长连接的建立过程
- 客户端向服务器在发送请求报文的同时,在首部添加发送 Connection 字段。
- 服务器收到请求并处理 Connection 字段。
- 服务器返回
Connection: keep-alive给客户端。 - 客户端接收到 Connection 字段,Keep-Alive 连接建立成功。
Keep-Alive 长连接的关闭过程
客户端请求断开连接的过程
- 客户端向服务器发送
Connection: close。 - 服务器收到请求并处理 Connection 字段,返回响应资源并主动断开连接(发 FIN 连接释放请求)。
- 客户端收到响应,确认连接关闭。
服务端主动断开连接的过程(比如空闲超时)
- 服务端在某个响应里加上
Connection: close(或什么都不加,直接发 FIN 连接释放请求)。 - 客户端收到响应后,也关闭连接。
短连接的服务端主动断开过程
- 客户端向服务器只是发送内容报文(不包含
Connection: keep-alive)。 - 服务器收到请求并处理,返回客户端请求的资源并主动断开连接(发 FIN 连接释放请求)。
- 客户端接收资源,发现没有 Connection 字段,也关闭连接。
开启 Keep-Alive 的优点
- 较少的 CPU 和内存的使用。(因为同时打开的连接减少了)
- 允许请求和应答的 HTTP 管线化。(HTTP 管线化,HTTP Pipelining,是一种在同一个 Keep-Alive 长连接上,客户端可以连续发送多个请求,而不必等待每个响应返回的技术;它的局限性是服务器必须严格按照请求顺序返回响应,容易出现“队头堵塞”,HTTP/2 引入了多路复用,在一个连接上可以乱序发送请求和响应,彻底解决了管线化的问题)
- 降低拥塞控制。(因为 TCP 连接减少了)
- 减少了后续请求的延迟。(因为无需再进行握手)
- 报告错误无需关闭 TCP 连接。
开启 Keep-Alive 的缺点
- 长时间的 TCP 连接容易导致系统资源无效占用,浪费系统资源。
HTTP 请求报文的组成(重点)
请求报文的四部分组成
| 部分 | 说明 |
|---|---|
| 请求行 | 包括请求方法字段、URL 字段、HTTP 协议版本字段,用空格分隔 例如: GET /index.html HTTP/1.1 |
| 请求头 | 由关键字/值对组成,每行一对,关键字和值用英文冒号分隔 如 User-Agent、Accept、Host 等 |
| 空行 | 请求头和请求体之间的分隔 |
| 请求体 | POST、PUT 等请求携带的数据 |
HTTP 响应报文的组成(重点)
响应报文的四部分组成
| 部分 | 说明 |
|---|---|
| 响应行 | 由网络协议版本、状态码和状态码的原因短语组成 例如: HTTP/1.1 200 OK |
| 响应头 | 由响应首部字段组成 |
| 空行 | 响应头和响应体之间的分隔 |
| 响应体 | 服务器响应的数据 |
HTTP 协议的优点和缺点(重点)
HTTP 是超文本传输协议,定义了客户端和服务器之间交换报文的格式和方式。它使用 TCP 作为传输层协议,保证了数据传输的可靠性,默认使用 80 端口。
优点
(1)支持客户端/服务器模式
客户端/服务器模式(Client/Server Model)是一种分布式计算架构,客户端即请求服务的程序(如浏览器),服务器即提供服务的程序(如 Web 服务器),两者通过网络进行通信。
关键特性包括:
- 请求-响应模型:客户端必须先发起请求,在 HTTP/1.0、HTTP/1.1 中服务器不能主动推送数据
- 无状态性:每个请求独立,服务器不保存客户端状态(通过 Cookie/Session 解决状态管理)
- 明确的角色分离:客户端负责用户界面、请求发起、响应处理,服务器负责数据存储、业务逻辑、资源管理
(2)简单快速
客户向服务器请求服务时,只需传送请求方法和路径。由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快。
(3)无连接
无连接就是限制每次连接只处理一个请求。HTTP/1.0 默认无连接(短连接),HTTP/1.1 起默认长连接。
服务器处理完客户的请求,并收到客户的应答后,即断开连接,节省传输时间。
(4)无状态
HTTP 协议是无状态协议。 这里的状态是指通信过程的上下文信息。
当服务器不需要处理会话状态(即无需依赖先前请求的信息)时,HTTP 请求的应答通常更快。
(5)灵活
HTTP 允许传输任意类型的数据对象。 正在传输的类型由 Content-Type 加以标记。
缺点
(1)无状态
HTTP 是一个无状态的协议,HTTP 服务器不会保存关于客户的任何信息。
缺少状态意味着如果后续处理需要前面的信息,则必须重传,这样会导致每次连接传送的数据量增大。
(2)明文传输
协议中的报文使用的是文本形式,这就直接暴露给外界,不安全。
(3)不安全
- 通信使用明文(不加密),内容可能会被窃听
- 不验证通信方的身份,因此有可能遭遇伪装
- 无法证明报文的完整性,所以有可能已遭篡改
URL 的组成部分(重点)
URL 示例:http://www.aspxfans.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name
一个完整的 URL 的七个部分
| 部分 | 示例 | 说明 |
|---|---|---|
| 协议部分 | http: | 代表网页使用的是 HTTP 协议 在互联网中可以使用多种协议,如 HTTP、FTP 等等。在 http: 后面的 // 为分隔符 |
| 域名部分 | www.aspxfans.com | 一个 URL 中,也可以使用 IP 地址作为域名使用 |
| 端口部分 | :8080 | 跟在域名后面的是端口,域名和端口之间使用 : 作为分隔符 端口不是一个 URL 必须的部分,如果省略端口部分,将采用默认端口(HTTP 协议默认端口是 80,HTTPS 协议默认端口是 443) |
| 虚拟目录部分 | /news/ | 从域名后的第一个 / 开始到最后一个 / 为止,是虚拟目录部分 虚拟目录也不是一个 URL 必须的部分 |
| 文件名部分 | index.asp | 从域名后的最后一个 / 开始到 ? 为止,是文件名部分 如果没有 ?,则是从域名后的最后一个 / 开始到 # 为止,是文件部分 如果没有 ? 和 #,那么从域名后的最后一个 / 开始到结束,都是文件名部分 文件名部分也不是一个 URL 必须的部分,如果省略该部分,则使用默认的文件名 |
| 锚部分 | name | 从 # 开始到最后,都是锚部分 锚部分也不是一个 URL 必须的部分 |
| 参数部分 | boardID=5&ID=24618&page=1 | 从 ? 开始到 # 为止之间的部分为参数部分,又称搜索部分、查询部分 参数可以允许有多个参数,参数与参数之间用 & 作为分隔符 |
POST 和 PUT 请求的区别
POST 请求
是向服务器端发送数据,该请求会改变数据的种类等资源,它会创建新的内容。
可以理解为是创建数据。
PUT 请求
是向服务器端发送数据,从而修改数据的内容,但是不会增加数据的种类等,也就是说无论进行多少次 PUT 操作,其结果并没有不同。
可以理解为是更新数据。
GET 方法 URL 长度限制的原因
实际上,HTTP 协议规范并没有对 GET 方法请求的 URL 长度进行限制,这个限制是特定的浏览器及服务器对它的限制。
IE 对 URL 长度的限制是 2083 字节。 由于 IE 浏览器对 URL 长度的允许值是最小的,所以开发过程中,只要 URL 的长度不超过 2083 字节,那么在所有浏览器中工作都不会有问题。
GET 的长度值 = URL(2083)- (你的 Domain + Path) - 2(2 是 GET 请求中 ?= 两个字符的长度)
主流浏览器对 GET 方法中 URL 的长度限制范围
| 浏览器 | 限制 |
|---|---|
| Microsoft Internet Explorer | IE 浏览器对 URL 的最大限制为 2083 个字符,如果超过这个数字,提交按钮没有任何反应 |
| Firefox | 对于 Firefox 浏览器 URL 的长度限制为 65536 个字符 |
| Safari | URL 最大长度限制为 80000 个字符 |
| Opera | URL 最大长度限制为 190000 个字符 |
| Google Chrome | URL 最大长度限制为 8182 个字符 |
主流的服务器对 GET 方法中 URL 的长度限制范围
| 服务器 | 限制 |
|---|---|
| Apache | 能接受最大 URL 长度为 8192 个字符 |
| Microsoft Internet Information Server(IIS) | 能接受最大 URL 的长度为 16384 个字符 |
页面有多张图片,HTTP 是怎样的加载表现?
-
在 HTTP/1 下,浏览器对一个域名下最大 TCP 连接数为 6,所以会请求多次。
- 可以用多域名部署解决,这样可以提高同时请求的数量,加快页面图片的获取速度。
-
在 HTTP/2 下,可以一瞬间加载出来很多资源,因为 HTTP/2 支持多路复用,可以在一个 TCP 连接中发送多个 HTTP 请求。
HTTP/2 的头部压缩算法
HTTP/2 的头部压缩是 HPACK 算法。在客户端和服务器两端建立“字典”,用索引号表示重复的字符串,采用哈夫曼编码来压缩整数和字符串,可以达到 50%~90% 的高压缩率。
具体内容
-
在客户端和服务器端使用“首部表“来跟踪和存储之前发送的键值对,对于相同的数据,不再通过每次请求和响应发送。
-
首部表在 HTTP/2 的连接存续期内始终存在,由客户端和服务器共同渐进地更新。
-
每个新的首部键值对要么被追加到当前表的末尾,要么替换表中之前的值。
例如,请求一发送了所有的头部字段,第二个请求则只需要发送差异数据,这样可以减少冗余数据,降低开销。
HTTP 协议的性能
HTTP 协议是基于 TCP/IP,并且使用了请求-应答的通信模式,所以性能的关键就在这两点里。
长连接
HTTP 协议有两种连接模式,一种是非持续连接,一种是持续连接。
-
非持续连接:指的是服务器必须为每一个请求的对象建立和维护一个全新的连接。
-
持续连接:指的是 TCP 连接默认不关闭,可以被多个请求复用。采用持续连接的好处是可以避免每次建立 TCP 连接三次握手时所花费的时间。
对于不同版本,采用不同的连接方式:
-
在 HTTP/1.0 每发起一个请求,都要新建一次 TCP 连接(三次握手),而且是串行请求,做了无谓的 TCP 连接建立和断开,增加了通信开销。
- 该版本使用的是非持续的连接,但是可以在请求时,加上
Connection: keep-alive来要求服务器不要关闭 TCP 连接。
- 该版本使用的是非持续的连接,但是可以在请求时,加上
-
在 HTTP/1.1 提出了长连接的通信方式,也叫持久连接。这种方式的好处在于减少了 TCP 连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。
- 该版本及以后版本默认采用的是持续的连接。
- 目前对于同一个域,大多数浏览器支持同时建立 6 个长连接。
管道网络传输
HTTP/1.1 采用了长连接的方式,这使得管道网络传输成为了可能。
管道(Pipeline)网络传输是指:可以在同一个 TCP 连接里面,客户端可以发起多个请求,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。但是服务器还是按照顺序回应请求,如果前面的回应特别慢,后面就会有许多请求排队等着,这称为“队头堵塞”。
队头堵塞
HTTP 传输的报文必须是一发一收,但是,里面的任务被放在一个任务队列中串行执行,一旦队首的请求处理太慢,就会阻塞后面请求的处理,这就是 HTTP 的“队头堵塞”问题。
解决方案:
- 并发连接:对于一个域名允许分配多个长连接,那么相当于增加了任务队列,不至于一个队伍的任务阻塞其它所有任务。
- 域名分片:将域名分出很多二级域名,它们都指向同样的一台服务器,能够并发的长连接数变多,解决了“队头堵塞”的问题。
与缓存相关的 HTTP 请求头
强缓存
| 请求头 | 说明 |
|---|---|
| Cache-Control | HTTP/1.1 引入,优先级高于 Expires,可精确控制缓存行为 |
| Expires | HTTP/1.0 引入,指定资源的过期时间(绝对时间) |
协商缓存
| 请求头/响应头 | 说明 |
|---|---|
| Etag / If-None-Match | 基于资源内容的哈希值进行比对,优先级高于 Last-Modified |
| Last-Modified / If-Modified-Since | 基于资源的最后修改时间进行比对 |
说一下 HTTP/3
HTTP/3 基于 UDP 协议实现了类似于 TCP 的多路复用数据流、传输可靠性等功能,这套功能被称为 QUIC 协议。
(1)流量控制、传输可靠性功能
QUIC 在 UDP 的基础上增加了一层来保证数据传输可靠性,它提供了数据包重传、拥塞控制、以及其他一些 TCP 中的特性。
(2)集成 TLS 加密功能
目前 QUIC 使用 TLS 1.3,减少了握手所花费的 RTT 数。
RTT 的全称是 Round-Trip Time,中文常译为往返时延或往返时间,是一个数据包从发送端出发、到达接收端、再返回到发送端,整个过程所需的总时间。TCP 著名的“三次握手”,即 TCP 建立连接本身就需要至少 1 个 RTT,之后才能开始传输实际数据。
(3)多路复用
同一物理连接上可以有多个独立的逻辑数据流,实现了数据流的单独传输,解决了 TCP 的“队头堵塞”问题。
(4)快速握手
由于基于 UDP,可以实现使用 0 ~ 1 个 RTT 来建立连接。
-
0 个 RTT:这是 QUIC 的强大优势。当客户端之前已经连接过某个服务器,它可以缓存一些密钥信息。在下次重连时,客户端可以在第一个数据包中就携带加密的应用程序数据,无需等待握手完成。从用户角度看,连接建立和数据传输同时开始,感觉像是 0 RTT 就建立了连接,极大地提升了速度。
-
1 个 RTT:在 QUIC 的首次连接中,客户端和服务器需要交换一些加密信息来建立安全连接,这个过程大约需要 1 个 RTT。虽然和 TCP 的 1 个 RTT 数字相同,但 QUIC 在握手的同时就可以开始传输应用数据,效率更高。
本文详细介绍了 HTTP 协议的基础知识,涵盖了常见的 HTTP 请求方法及对比、常见的 HTTP 请求头和响应头、HTTP/1.0、HTTP/1.1、HTTP/2 之间的区别、HTTP 和 HTTPS 协议的区别、HTTP 请求报文和响应报文的组成等核心内容。掌握这些 HTTP 协议的基础知识,对于前端开发和网络编程都至关重要,能够帮助我们更好地理解 Web 应用的工作原理,优化网络性能,提升用户体验。