1.HTTP 是什么?
HTTP 是超文本传输协议 ,HTTP 是一个在计算机世界里专门在「两点」之间「传输」文字、图片、音频、视频等「超文本」数据的「约定和规范」。
HTTP 常见的状态码有哪些?
- 100类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。
- 200类状态码表示服务器成功处理了客户端的请求。
- 300类状态码表示客户端请求的资源发生了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向。 301 和 302 都会在响应头里使用字段 Location,指明后续要跳转的 URL,浏览器会自动重定向新的 URL。
- 400类状态码表示客户端发送的报文有误,服务器无法处理。
- 500类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。
HTTP缓存有哪些实现方式?
什么是http缓存?
对于一些具有重复性的 HTTP 请求,比如每次请求得到的数据都一样的,我们可以把这对「请求-响应」的数据都缓存在本地,那么下次就直接读取本地的数据,不必在通过网络获取服务器的响应了。
什么是强制缓存?
强缓存指的是只要浏览器判断缓存没有过期,则直接使用浏览器的本地缓存,决定是否使用缓存的主动性在于浏览器这边。一般使用Cache-Controlhttp响应头部字段 来实现强缓存。
什么是协商缓存?
当我们在浏览器使用开发者工具的时候,某些请求的响应码是 304,这个是告诉浏览器可以使用本地缓存的资源,通常这种通过服务端告知客户端是否可以使用缓存的方式被称为协商缓存。
协商缓存就是与服务端协商之后,通过协商结果来判断是否使用本地缓存。
GET 和 POST 有什么区别?
- 在 HTTP 协议里,所谓的「安全」是指请求方法不会「破坏」服务器上的资源。
- 所谓的「幂等」,意思是多次执行相同的操作,结果都是「相同」的。
- 在 HTTP 协议中,GET 和 POST 是两种常用的请求方法,它们的主要区别在于用途和数据传输方式。
GET
- 根据 RFC 规范,GET 的语义是从服务器获取指定的资源,这个资源可以是静态的文本、页面、图片视频等。GET 请求的参数位置一般是写在 URL 中,URL 规定只能支持 ASCII,所以 GET 请求的参数只允许 ASCII 字符 ,而且浏览器会对 URL 的长度有限制。
- 比如,你打开我的文章,浏览器就会发送 GET 请求给服务器,服务器就会返回文章的所有文字及资源。
POST
- 主要用于向服务器提交数据,通常用于表单提交。根据 RFC 规范,POST 的语义是根据请求负荷(报文body)对指定的资源做出处理,具体的处理方式视资源类型而不同。POST 请求携带数据的位置一般是写在报文 body 中,body 中的数据可以是任意格式的数据,只要客户端与服务端协商好即可,而且浏览器不会对 body 大小做限制。
- 比如,在评论区留言浏览器就会执行一次 POST 请求,把你的留言文字放进了报文 body 里,然后拼接好 POST 请求头,通过 TCP 协议发送给服务器。
GET 和 POST 方法都是安全和幂等的吗?
GET 方法就是安全且幂等的,因为它是「只读」操作,无论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。所以,可以对 GET 请求的数据做缓存,GET 请求可以保存为书签。
POST 因为是「新增或提交数据」的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据就会创建多个资源,所以不是幂等的。所以,浏览器一般不会缓存 POST 请求,也不能把 POST 请求保存为书签。
GET 请求可以带 body 吗?
RFC 规范并没有规定 GET 请求不能带 body 的。理论上,任何请求都可以带 body 的。只是因为 RFC 规范定义的 GET 请求是获取资源,所以根据这个语义不需要用到 body。
另外,URL 中的查询参数也不是 GET 所独有的,POST 请求的 URL 中也可以有参数的。
HTTP和HTTPS的区别?
HTTP 是超文本传输协议,信息是明文传输,存在安全风险的问题。HTTPS 则解决 HTTP 不安全的缺陷,在 TCP 和 HTTP 网络层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。
HTTP 连接建立相对简单, TCP 三次握手之后便可进行 HTTP 的报文传输。而 HTTPS 在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程,才可进入加密报文传输。
两者的默认端口不一样,HTTP 默认端口号是 80,HTTPS 默认端口号是 443。
HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。
HTTP1.1的特点
优点
1. 简单
基本的报文格式就是 header + body,头部信息也是 key-value 简单文本的形式,易于理解
2.灵活和易于扩展
HTTP 协议里的各类请求方法、URI/URL、状态码、头字段等每个组成要求都没有被固定死,都允许开发人员自定义和扩充。同时 HTTP 由于是工作在应用层( OSI 第七层),则它下层可以随意变化,比如:
- HTTPS 就是在 HTTP 与 TCP 层之间增加了 SSL/TLS 安全传输层;
- HTTP/1.1 和 HTTP/2.0 传输协议使用的是 TCP 协议,而到了 HTTP/3.0 传输协议改用了 UDP 协议。
3.应用广泛和跨平台
缺点
1. 无状态
无状态的好处,因为服务器不会去记忆 HTTP 的状态,所以不需要额外的资源来记录状态信息,这能减轻服务器的负担,能够把更多的 CPU 和内存用来对外提供服务。
无状态的坏处,既然服务器没有记忆能力,它在完成有关联性的操作时会非常麻烦。
用 Cookie 技术。Cookie 记录用户的访问信息和偏好设置,存储用户的登录状态,使用户在返回网站时不必重新登录。。2.不安全
HTTP 比较严重的缺点就是不安全:
通信使用明文(不加密),内容可能会被窃听。
不验证通信方的身份,因此有可能遭遇伪装。
无法证明报文的完整性,所以有可能已遭篡改。
HTTP 的安全问题,可以用 HTTPS 的方式解决,也就是通过引入 SSL/TLS 层,使得在安全上达到了极致。
性能:
1. 长连接
HTTP/1.0 每发起一个请求,都要新建一次 TCP 连接(三次握手),增加了通信开销。
HTTP/1.1 提出了长连接的通信方式,也叫持久连接。这种方式的好处在于减少了 TCP 连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。
持久连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态。某个 HTTP 长连接超过一定时间没有任何数据交互,服务端就会主动断开这个连接
2. 管道网络传输
在同一个 TCP 连接里面,客户端可以发起多个请求。服务器必须按照接收请求的顺序发送对这些管道化请求的响应。
HTTPS 解决了 HTTP 的哪些问题?
HTTP 由于是明文传输,通信使用明文(不加密),内容可能会被窃听。窃听风险。不验证通信方的身份,因此有可能遭遇伪装。冒充风险。无法证明报文的完整性,所以有可能已遭篡改。篡改风险。
HTTPS 在 HTTP 与 TCP 层之间加入了 SSL/TLS 协议,可以很好的解决了上述的风险:
- 信息加密:混合加密的方式实现信息的机密性,解决了窃听的风险。
- 校验机制:摘要算法的方式来实现完整性,它能够为数据生成独一无二的「指纹」,指纹用于校验数据的完整性,解决了篡改的风险。
- 身份证书:将服务器公钥放入到数字证书中,解决了冒充的风险。
摘要算法
对内容计算出一个「指纹」,然后同内容一起传输给对方。对方收到后,先是对内容也计算出一个「指纹」,然后跟发送方发送的「指纹」做一个比较,如果「指纹」相同,说明内容没有被篡改。
摘要算法(哈希函数)来计算出内容的哈希值,也就是内容的「指纹」,这个哈希值是唯一的,且无法通过哈希值推导出内容。
数字签名
非对称加密算法来解决,共有两个密钥:
一个是公钥,这个是可以公开给所有人的;
一个是私钥,这个必须由本人管理,不可泄露。公钥加密,私钥解密。这个目的是为了保证内容传输的安全,因为被公钥加密的内容,其他人是无法解密的,只有持有私钥的人,才能解密出实际的内容;
私钥加密,公钥解密。这个目的是为了保证消息不会被冒充,因为私钥是不可泄露的,如果公钥能正常解密出私钥加密的内容,就能证明这个消息是来源于持有私钥身份的人发送的。私钥加密内容不是内容本身,而是对内容的哈希值加密。
数字证书
服务器把自己的公钥注册到数字证书认证机构CA,CA用自己的私钥对服务器的公钥数字签名(私钥加密内容,公钥解密内容)颁发数字证书。客户端拿到CA的数字签名和服务器的公钥后,能用CA的公钥解密,解密成功就说明数字证书真实。与服务器建立通信。
中间人攻击以及如何防范?
客户端通过浏览器向服务端发起 HTTPS 请求时,被「假基站」转发到了一个「中间人服务器」,于是客户端是和「中间人服务器」完成了 TLS 握手,然后这个「中间人服务器」再与真正的服务端完成 TLS 握手。
通过 HTTPS 双向认证来避免这种问题:一般 HTTPS 是单向认证,客户端只会验证了服务端的身份,但是服务端并不会验证客户端的身份。如果用了双向认证方式,不仅客户端会验证服务端的身份,而且服务端也会验证客户端的身份。服务端一旦验证到请求自己的客户端为不可信任的,服务端就拒绝继续通信,客户端如果发现服务端为不可信任的,那么也中止通信。
HTTP1.0、HTTP1.1、HTTP2.0和HTTP3.0的区别?
HTTP/1.1 相比 HTTP/1.0 提高了什么性能?
- 长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。
- 支持管道(pipeline)网络传输
http1.1的性能瓶颈
- 请求 / 响应头部(Header)未经压缩就发送,首部信息越多延迟越大。只能压缩
Body
的部分;
- 服务器是按请求的顺序响应的,如果服务器响应慢,会招致客户端一直请求不到数据,也就是队头阻塞;
- 请求只能从客户端开始,服务器只能被动响应。
HTTP/2.0
HTTP/2 协议是基于 HTTPS 的,所以 HTTP/2 的安全性也是有保障的。
- 头部压缩
压缩头(Header)如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分
- 二进制格式
HTTP/2 不再像 HTTP/1.1 里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧(frame):头信息帧(Headers Frame)和数据帧(Data Frame)。增加了数据传输的效率。
- 并发传输
HTTP/1.1 的实现是基于请求-响应模型,完成一个事务(请求与响应),才能处理下一个事务,响应迟迟不来会造成队头阻塞。
HTTP/2 引出了 Stream 概念,多个 Stream 复用在一条 TCP 连接。Stream 里可以包含 1 个或多个 Message,Message 对应 HTTP/1 中的请求或响应,由 HTTP 头部和报文构成。
针对不同的 HTTP 请求用独一无二的 Stream ID 来区分,接收端可以通过 Stream ID 有序组装成 HTTP 消息,不同 Stream 的帧是可以乱序发送的,因此可以并发不同的 Stream ,也就是 HTTP/2 可以并行交错地发送请求和响应。
- 服务器主动推送资源
服务端不再是被动地响应,可以主动向客户端发送消息。客户端和服务器双方都可以建立 Stream, Stream ID 也是有区别的,客户端建立的 Stream 必须是奇数号,而服务器建立的 Stream 必须是偶数号。
HTTP2的缺陷
HTTP/2 是基于 TCP 协议来传输数据的,TCP 是字节流协议,TCP 层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给 HTTP 应用,那么当「前 1 个字节数据」没有到达时,后收到的字节数据只能存放在内核缓冲区里,只有等到这 1 个字节数据到达时,HTTP/2 应用层才能从内核中拿到数据,这就是 HTTP/2 队头阻塞问题。
HTTP/3.0
HTTP/3 把 HTTP 下层的 TCP 协议改成了 UDP
- 1.无队头阻塞
QUIC 有自己的一套机制可以保证传输的可靠性的。当某个流发生丢包时,只会阻塞这个流,其他流不会受到影响,因此不存在队头阻塞问题。
- 2.更快的连接(0-RTT 和 1-RTT 握手)
1. 整合 TLS 与传输层
传统 TCP + TLS:
TCP 需要 1-RTT 完成三次握手,TLS 1.2 需要额外 2-RTT 完成密钥协商(如 RSA 握手),总耗时 3-RTT。即使 TLS 1.3 优化到 1-RTT,TCP + TLS 仍需 2-RTT(TCP 1-RTT + TLS 1-RTT)。QUIC 的整合设计:
QUIC 直接内嵌 TLS 1.3,将传输层和加密层合并为单一协议。首次连接时,QUIC 在 1-RTT 内同时完成连接建立和密钥交换(类似 TLS 1.3 的 1-RTT 握手),无需等待 TCP 握手完成后再进行 TLS 协商。2. 0-RTT 会话恢复
会话缓存机制:
当客户端与服务端首次完成连接后,QUIC 会缓存会话密钥(Session Ticket)。后续连接时,客户端可直接使用缓存的密钥加密数据,无需重新协商密钥,实现 0-RTT 数据传输(即第一个数据包即可携带应用层数据)。TTP/1 和 HTTP/2 协议,TCP 和 TLS 是分层的,分别属于内核实现的传输层、openssl 库实现的表示层,因此它们难以合并在一起,需要分批次来握手,先 TCP 握手,再 TLS 握手。
HTTP/3 的 QUIC 协议并不是与 TLS 分层,而是 QUIC 内部包含了 TLS.它在自己的帧会携带 TLS 里的“记录”,因此能实现更快的链接。
- 3.连接迁移
在 TCP 中,连接完全依赖四元组标识。当任一元素(如 IP 或端口)变化时,连接会被认为“中断”,当移动设备的网络从 4G 切换到 WIFI 时,意味着 IP 地址变化了,那么就必须要断开连接,然后重新建立连接。
QUIC 协议没有用四元组的方式来“绑定”连接,而是通过连接 ID 来标记通信的两个端点,客户端和服务器可以各自选择一组 ID 来标记自己,即使客户端的端口发生变化只要连接 ID不变,就可以使用原连接,达到了连接迁移的功能。
QUIC协议的概念和特点?
基于 UDP 实现的可靠传输协议
要基于 UDP 实现的可靠传输协议,那么就要在应用层下功夫,也就是要设计好协议的头部字段。
1.Packet Header
- Long Packet Header 用于首次建立连接。
- Short Packet Header 用于日常传输数据。
Short Packet Header 中的
Packet Number
是每个报文独一无二的编号,它是严格递增的,也就是说就算 Packet N 丢失了,重传的 Packet N 的 Packet Number 已经不是 N,而是一个比 N 大的值。
- 可以更加精确计算 RTT,没有 TCP 重传的歧义性问题;
- 可以支持乱序确认,因为丢包重传将当前窗口阻塞在原地,而 TCP 必须是顺序确认的,丢包时会导致窗口不滑动;
2.Stream ID 与 Offset 字段
- Stream ID 作用:多个并发传输的 HTTP 消息,通过不同的 Stream ID 加以区别,类似于 HTTP2 的 Stream ID;
- Offset 作用:类似于 TCP 协议中的 Seq 序号,保证数据的顺序性和可靠性;
假设数据包 Packet N 丢失了,后面重传该数据包的编号为 Packet N+2,丢失的数据包和重传的数据包 Stream ID 与 Offset 都一致,说明这两个数据包的内容一致。
QUIC 通过单向递增的 Packet Number,配合 Stream ID 与 Offset 字段信息,可以支持乱序确认而不影响数据包的正确组装,摆脱了TCP 必须按顺序确认应答 ACK 的限制,解决了 TCP 因某个数据包重传而阻塞后续所有待发送数据包的问题。
怎么彻底解决队头阻塞的问题的?
1.TCP 队头阻塞的问题,其实就是接收窗口的队头阻塞问题。当接收窗口收到的数据不是有序的,比如收到第 33~40 字节的数据,由于第 32 字节数据没有收到, 接收窗口无法向前滑动,那么即使先收到第 33~40 字节的数据,这些数据也无法被应用层读取的。
导致接收窗口的队头阻塞问题,是因为 TCP 必须按序处理数据,也就是 TCP 层为了保证数据的有序性,只有在处理完有序的数据后,滑动窗口才能往前滑动,否则就停留,停留「接收窗口」会使得应用层无法读取新的数据。
2.HTTP/2 多个 Stream 请求都是在一条 TCP 连接上传输,这意味着多个 Stream 共用同一个 TCP 滑动窗口,那么当发生数据丢失,滑动窗口是无法往前移动的,此时就会阻塞住所有的 HTTP 请求,这属于 TCP 层队头阻塞。
3.QUIC 给每一个 Stream 都分配了一个独立的滑动窗口,这样使得一个连接上的多个 Stream 之间没有依赖关系,都是相互独立的,各自控制的滑动窗口。
http报文格式
请求报文
1.请求行(Request Line):包括请求方法(GET、POST)、请求的资源路径(url)和使用的协议版本(http 版本1.0/1.1/2.0)。
GET /index.html HTTP/1.1 (用空格作为分隔符)
- GET 是请求方法,指示服务器获取资源。
- /index.html 是请求的资源路径。
- HTTP/1.1 是协议版本。
2.请求头部(报头)(Request Headers):包括关于客户端请求的其他信息,如主机名、用户代理、接受的内容类型等。大部分是键值对(Key:Value)。包含有content-Length:xx。表示请求正文的长度,用它当作读取正文的规定
- Host: www.example.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64;
- x64) Accept:
- text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
3.空行:请求头部与请求体之间必须有一个空行。
4.请求体(Request Body):对于一些请求(如 POST 请求),可能包含发送给服务器的数据,比如表单数据或上传的文件内容。
响应报文
一个标准的 HTTP 响应由以下几部分组成:
1.状态行(Status Line):包括协议版本、状态码和相应的状态消息。
HTTP/1.1 200 OK HTTP/1.1 是协议版本。 200 是状态码,表示请求成功。 OK 是状态消息。
2.响应头部(Response Headers):包括关于响应的其他信息,如服务器类型、响应时间、内容类型等。
Server: Apache/2.4.41 (Unix) Content-Type: text/html; charset=utf-8
Content-Length: 1234
3.空行:响应头部与响应体之间必须有一个空行。
4.响应体(Response Body):服务器返回给客户端的实际内容,如 HTML 页面、JSON 数据等。
<!DOCTYPE html>
<html>
<head>
<title>Example Page</title> </head> <body>
<h1>Hello, World!</h1> </body> </html>
Cookie和Session和Token的定义区别是什么
-
Cookie
-
客户端存储:由服务器生成并发送到浏览器的小型文本文件,存储在客户端(如
document.cookie
)。 -
用途:保存用户偏好、会话标识(如Session ID)、登录Token等非敏感数据。
-
特性:可设置过期时间(会话级或持久化)、大小限制(通常≤4KB)、通过HTTP头部自动传输。
-
-
Session
-
服务端存储:用户会话数据存储在服务器(如内存、数据库、Redis),客户端仅保存Session ID(通常通过Cookie传递)。
-
用途:管理敏感信息(如用户权限、购物车数据),依赖服务端状态。
-
特性:默认生命周期短(关闭浏览器或超时失效),需服务端资源维护。
-
-
Token
-
无状态凭证:服务器生成的加密字符串(如JWT),包含用户身份信息及签名,客户端存储并在请求时携带(如Header)。
-
用途:身份验证(如API鉴权),替代传统Session实现无状态服务。
-
特性:自包含(无需服务端存储)、支持分布式系统、可设置有效期。
-