HTTP
一、HTTP Status Code
状态码的分类:
- 1XX: Informational(请求正在处理)
- 2XX Success(请求成功)
- 3XX Redirection(重定向) 需要进一步操作以完成请求
- 4XX Client Error(客户端错误)请求包含语法错误或无法完成请求
- 5XX Server Error(服务器错误)服务器在处理请求的过程中发生了错误
常见状态码:
- 100 Continue 客户端继续发送请求,这是临时响应
everything so far is OK
这个临时响应,是用来通知客户端,它的部分请求已经被服务器接收,且仍未被拒绝。
客户端应当继续发送请求的剩余部分。
若请求已经完成,忽略这个响应。
服务器必须在请求完成后向客户端发送一个最终响应
常用于POST大数据传输: 客户端在发送POST数据给服务器前,征询服务器情况。看服务器是否处理POST的数据,若不处理,则不上传POST数据,如果处理,则POST上传数据
200 OK
请求正常处理204 No Content 无内容
服务器成功处理,但未返回内容(一般用于只需客户端向服务端发送消息)206 Partial Content 部分内容
服务器成功处理了部分请求
一般用来做断点续传,或者是视频文件等大文件的加载
301 Moved Permanently 永久移动
请求的资源已被永久的移动到新URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替302 Found 临时移动
资源原本确实存在,但已经被临时改变了URI。由于重定向是临时发生的,所以客户端在之后的请求中还应该使用原本的 URI。304 Not Modified
自从上次请求后,请求的资源未被修改过。307 Temporary Redirect
状态码 307 与 302 之间的唯一区别:当发送重定向请求的时候,307 状态码可以确保请求方法和消息主体不会发生变化。当响应状态码为 302 的时候,一些旧有的用户代理会错误地将请求方法转换为 GET400 Bad Request
客户端请求的语法错误,服务器无法理解401 Unauthorized
未授权, 请求要求身份验证403 Forbidden
服务器理解请求客户端的请求,但是拒绝执行404 Not Found
服务器无法根据客户端的请求找到资源405 Method Not Allowed
请求方法被服务端识别,但是服务端禁止使用该方法500 Internal Server Error
服务器内部错误502 Bad Gateway
(错误网关) 服务器作为网关或代理,从上游服务器收到无效响应503 Service Unavailable
服务器暂时处于超负载或停机维护,目前无法处理请求504 Gateway Time-out
(网关超时)充当网关或代理的服务器,未及时从上游服务器收到请求
二、 HTTP 缓存
缓存是一种保存资源副本并在下次请求时直接使用该副本的技术
客户端为了加快速度会缓存部分资源,但是下次请求时,客户端不知道这个资源有没有更新,服务端也不晓得客户端缓存的是哪个版本、该不该再返回资源,
HTTP缓存策略就是来解决客户端和服务端的信息不对称问题。
对客户端来说,缓存减少了等待时间和流量;对服务器来说,减小了服务端压力。
协商缓存
为了知道资源有没有更新,必须每次和服务端沟通过才知道,称为协商缓存
浏览器第一次请求数据后,会将数据和response header的缓存标识存储起来。
再次请求时,带上存储的头部字段,向服务器端验证是否可用。
如果返回 304 Not Modified,代表资源没有改变,可以使用缓存,获取新的过期时间。
反之返回 200, 就需要替换旧资源。
ETag (response headers) 和If-None-Match (request headers)
ETag是一个资源的标识符,具体返回什么值要看服务器的计算策略。
客户端拿到后会将这个ETag和返回值一起存下来,等下次请求时,使用配套的If-None-Match,放到request header里。
当服务端拿到请求里面的If-None-Match跟当前版本的ETag比较:
如果一样,直接返回304,不返回内容(body),只返回header,告诉浏览器直接用缓存。
如果不一样,返回200和最新内容。Last-Modified (response headers) & If-Modified-Since (request headers)
Last-Modified 和 If-Modified-Since也是配套使用的,类似ETag和If-None-Match的关系。
不过ETag放的是一个版本号或者hash值,Last-Modified放的是资源的最后修改时间。
服务端拿到这个头后,会跟当前版本的修改时间进行比较:
当前版本的修改时间比这个晚,说明这个时间后又改过了,返回200和新的内容
当前版本的修改时间和这个一样,即没有更新,返回304,不返回body,只返回header,客户端直接使用缓存ETag 和 Last-Modified 优先级
ETag 和 Last-Modified都是协商缓存,都需要服务器进行计算和比较。
但是Last-Modified只能精确到秒。
ETag每次修改都会生成新的,优先级比Last-Modified高。
每次请求都要计算这个值,需要额外耗费资源。
强制缓存
强制缓存的优先级高于协商缓存。
强制缓存是知道在某个时间段内,完全不用去问服务端,直接用缓存就行。
Expires
Expires 指缓存过期的时间,超过了这个时间点就代表资源过期。
eg.Expires: Wed, 21 Oct 2000 07:28:00 GMT
有一个问题是如果时间表示出错,或者没有转换到正确的时区都可能造成缓存生命周期出错。
所以两个同时存在时, Cache-Control 优先级更高。Cache-Control
可由多个字段组合而成,相对比较复杂,可设置属性也比较多
max-age
指定一个时间长度,在这个时间段内缓存是有效的,单位是s
eg.Cache-Control: max-age=20000
这表示当前资源在20000秒内都不用再请求了,直接使用缓存。s-maxage
s-maxage 同 max-age,覆盖 max-age、Expires,但仅适用于共享缓存,在私有缓存中被忽略。
tips:
私有缓存:仅供一个用户使用的缓存,通常只存在于如浏览器这样的客户端上
共享缓存:可以供多个用户的缓存,存在于网络中负责转发消息的代理服务器(对热点资源常使用共享缓存,以减轻源服务器的压力,并提升网络效率)
immutable
表示这辈子都用缓存,再不可能请求no-store
所有内容都不会被缓存,不使用强制缓存,也不使用协商缓存no-cache
是否使用客户端缓存的内容,需要经过协商缓存来验证决定。
表示不使用 Cache-Control的缓存控制方式做前置验证,而是使用 Etag 或者Last-Modified字段来控制缓存。
- Expires 和 Cache-Control 优先级
若在Cache-Control响应头设置了 max-age 或者 s-maxage 指令,那么 Expires 头会被忽略。
实际应用
可以考虑缓存的内容:css样式文件,js文件,logo、图标,html文件,
不该被缓存的内容:业务敏感的GET请求
不经常改变的资源:
给max-age设置一个较大的值,一般max-age=31536000(一年)
比如引入的一些第三方文件、打包出来的带有hash后缀css、js文件。一般来说当文件内容改变,会更新版本号、hash值。
对于频繁变动的资源:
首先需要使用Cache-Control: no-cache 使浏览器每次都请求服务器,
然后配合 ETag 或者 Last-Modified 来验证资源是否有效。
这样的做法虽然不能减少请求数量,但是能显著减少响应数据大小。
三、HTTP 与 HTTPS 的区别
- HTTP 明文传输,数据未加密,安全性差,HTTPS(SSL/TLS + HTTP) 数据传输过程是加密的,安全性较好,可用于加密传输、身份验证
- http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
- HTTP 页面响应速度比 HTTPS 快,因为 HTTP 使用 TCP 三次握手建立连接,客户端和服务器需要交换 3 个包,而 HTTPS除了 TCP 的三个包,还要加上 ssl 握手需要的 9 个包,所以一共是 12 个包。
四、HTTPS的安全性
http是明文传输,是直接可以截取后进行查看、篡改的。
比如:
获取隐私信息;
修改服务端返回的信息,加入一个js广告文件、或者直接重定向到钓鱼网站
HTTPS是如何保证安全的
加密。
加密种类:
- 不可逆加密
比如密码不能明文存到数据库,一般要加密存起来,只要用户的输入经过同样的加密算法,对比一下即可知道是否正确,所以没必要可逆 - 可逆加密
- 对称加密: 用同一个密码加密和解密
- 非对称加密(publick key 和 private key): 用来保证数据安全性(私钥解密,公钥加密);用来判断身份(私钥签名,公钥验证)
HTTPS的加密方式:
浏览器拥有服务器的公钥,那浏览器生成一个密钥,用服务器的公钥加密传给服务端,然后服务端和浏览器以后拿这个密钥以对称加密的方式通信。
但存在隐患,服务端在把明文公钥传给浏览器时若被黑客截获,然后把数据包中的公钥替换成自己伪造的公钥(当然他自己有自己的私钥),浏览器本身是不知公钥的真假,所以浏览器依然按照之前的步骤,生成对称密钥,然后用假的公钥加密传递给服务端,这个时候,黑客截获到报文,然后用自己的私钥解密,拿到其中的对称密钥,然后再传给服务端。那以后的通信就全都暴露了。
根本原因就是浏览器无法确认自己收到的公钥是不是网站自己的。
如何保证浏览器收到的公钥一定是该网站的公钥
CA(Certificate Authority)机构办理的数字证书,里面包含了服务器公钥和签名时用的hash算法。
数字证书的主要内容包括:
- 服务器公钥;
- 域名;
- 持有者信息;
- 签发机构;
- CA 对这份文件的数字签名及使用的算法;
- 证书有效期;
- 还有一些其他额外信息;
为了防止服务器向浏览器发送证书的过程中,被篡改,需要给证书加数字签名。
数字签名的过程: CA机构拥有非对称加密的私钥和公钥 => CA对证书明文信息进行hash(非对称性的加密解密很消耗性能,证书的明文很长很长,hash后会短很多) => 对hash后的值用私钥加密,得到数字签名
浏览器收到服务器下发的证书后,证书里面的签名是CA机构用私钥签名的,所以只要用CA机构的公钥验证一下签名即可。
验证步骤如下:
拿到证书后,用里面的hash算法对明文内容进行hash运算,得到A
用CA的公钥解密签名,得到B
比较A 和 B,如果相等,说明没有被篡改,否则浏览器提示证书不可信。
浏览器内部都内置了各大CA机构的公钥信息
HTTPS如何保证完整性
实现完整性的手段主要是摘要算法,也就是常说的散列函数、哈希函数。
可以理解成一种特殊的压缩算法,它能够把任意长度的数据“压缩”成固定长度、而且独一无二的“摘要”字符串。
摘要算法保证了“数字摘要”和原文是完全等价的。
所以,我们只要在原文后附上它的摘要,
当网站收到后也计算一下消息的摘要,把这两份摘要做个对比,
如果一致,就说明消息是完整可信的,没有被修改
总结
如果证书被篡改,浏览器就提示不可信,终止通信,如果验证通过,说明公钥没问题,一定没被篡改。
公钥没被篡改,那浏览器生成的、用于对称加密的密钥用公钥加密发送给服务端,也只有服务端的私钥能解开,所以保证了对称密钥不可能被截获。
对称密钥没被截获,那双方的通信就是安全的。
摘要算法可以保证通信数据时完整的、未被篡改的。
五、 HTTPS握手
HTTPS是在HTTP的基础上提供了数据加密的支持,可以用来认证客户端和服务端的身份。
在普通的HTTP中,数据是明文传输, 很容易出现中间人伪装数据。在HTTPS中则使用了非对称公钥机制,对数据进行了加密,又能验证对方身份,基本避免中间人攻击。
HTTPS的加密是通过TLS(Transport Layer Security)安全传输层协议来实现的。
在客户端和服务端正常通信之前,会有一个握手过程:
- 首先,浏览器发起client hello消息,消息中包括:TLS版本、密码组合(供服务器选择)、客户端产生的(client random)随机数,这个随机数用于后续的密钥协商;
- 接着,服务器响应一个server hello消息,消息中包括:TLS版本、服务器选择的密码组合、服务器产生的随机数(server random),这个随机数用于后续的密钥协商;
- 再接着,服务器继续发送一个 certificate消息,附加服务器的证书;
- 最后,服务器发送一个 server hello done消息,用来通知客户端 server_hello 信息发送结束;
- 浏览器在收到服务器发来的证书后,验证是否是受信任的机构签发的,是否是真实的服务器;
- 认证服务器的身份后,浏览器生成随机字符串premaster secret(预主密钥),并用公钥加密传给服务器;
- 服务器接着使用私钥解密得到premaster secret;
- 然后,浏览器和服务器使用premaster secret和之前收到的对方的随机数,通过相同的算法生成相同的共享密钥master key,用于加密和解密后续所有的通信;
- 接着,浏览器发送用master key加密的 finished消息;
- 服务器接收并验证,发送用master key加密的 finished消息;
- 至此TLS握手完成,双方之后使用对称加密进行安全通信。
六、在URL输入网址敲击回车后,发生了什么?
- 过程
输入URL地址 –> 浏览器缓存 –> DNS域名解析 –> TCP三次握手 –> 发送HTTP请求
–> HTTP请求响应 –> 浏览器解析渲染页面 –> TCP四次挥手
URL
URL(Uniform Resource Locator),统一资源定位符,用于定位互联网上资源,俗称网址。
语法规则:scheme://host.domain:port/path/filename浏览器缓存
判断浏览器是否有对应的URL的资源的缓存DNS 域名解析
DNS(Domain Name System)服务提供域名到IP地址之间的解析。
用户通常使用主机名或域名来访问对方的计算机,而不是通过IP地址访问,DNS解析的过程就是寻找哪台机器上有所需资源。
过程如下:- 浏览器先检查自身缓存中有没有被解析过的这个域名对应的IP地址
- 浏览器缓存没命中,浏览器会检查操作系统缓存中有没有对应的已解析过的IP地址
- 操作系统缓存还没命中。会请求本地域名服务器(LDNS: Local DNS server)来解析这个域名
tips:一般是距离不远、性能很好的服务器。80%的域名解析到这里就会完成 - LDNS 仍然没有命中,就直接跳到 Root DNS Server 请求解析。
- Root DNS Server 给 Local DNS Server 返回gTLD Server地址。
tips: gTLD Server: Generic top-level domain,国际顶尖域名服务器,如.com .cn .org 等 - LDNS向gTLD Server发送解析请求
- 接受请求的 gTLD Server 查找并返回这个域名对应的 Name Server的地址
tips: 这个Name Server 就是网站注册的域名服务器 - Name Server根据映射关系表找到目标 IP,返回给 LDNS。
- LDNS 缓存这个域名和对应的 IP
- LDNS 把解析的结果返回给用户,用户缓存到本地系统中,域名解析过程至此结束。
- TCP三次握手
TCP (Transmission Control Protocol) 连接可以保证两端(发送端和接收端)的通信可达。
过程如下:- 客户端发送一个带 SYN=1,Seq=X 的数据包到服务器端口
- 服务器发回一个带 SYN=1, ACK=X+1, Seq=Y 的响应包以示传达确认信息
- 客户端再回传一个带 ACK=Y+1, Seq=Z 的数据包,代表“握手结束”
发送HTTP请求
一个 HTTP 请求报文由请求行(request line)、请求头部(headers)、空行(blank line)和请求数据(request body)4 个部分组成。HTTP响应请求
HTTP 响应报文由状态行(status line)、相应头部(headers)、空行(blank line)和响应数据(response body)4 个部分组成。浏览器解析并渲染界面
步骤
- 解析 HTML,生成 DOM 树
- 解析 CSS,生成 CSSOM 规则树
- 将 DOM 树和 CSSOM 树结合,去除不可见元素,生成渲染树( Render Tree )
- Layout (布局):根据生成的渲染树,进行布局( Layout ),计算各元素尺寸、位置等信息
- Paint (绘制): 根据计算好的信息绘制页面
tips:
使用 visibility 和 opacity 隐藏的节点,还是会显示在渲染树上的(因为还占据文档空间),只有 display : none 的节点才不会显示在渲染树上reflow 回流
布局完成后,发现了某部分的大小、位置发生了变化,影响了布局,浏览器重新渲染受到影响的部分。
每个页面至少需要一次回流,就是在页面第一次加载时,这时候是一定会发生回流的,因为要构建 Render Tree。repaint 重绘
屏幕的一部分重画,不影响整体布局,比如某个CSS的背景色变了,但元素的几何尺寸和位置不变。如何减少重绘与回流?
- CSS
- 避免使用table布局,因为可能很小的一个小改动会造成整个 table 的重新布局
- 使用visibility, 而不是 display: none, 因为visibility只引起重绘,display改变了布局,会引发回流
- CSS 选择器从右往左匹配查找,避免节点层级过多。可以使用性能更高的选择器,如类选择器
- 尽可能在DOM树的最末端改变class,限制回流的范围,使其影响尽可能少的节点。
- 为 img 指定宽高,避免图像加载完成后触发reflow
- JS
- 避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。
- 对具有复杂动画的元素使用absolute定位,使它脱离文档流
- 缓存布局信息
与布局信息相关的API会触发强制reflow / layout。
为了避免频繁读取布局信息相关的API,比如getComputedStyle,offsetWidth、clientTop、scrollHeight等。
可以按需缓存,利用变量保存读取的布局信息,供多次使用。 - GPU加速
合理利用特殊样式属性(如 transform: translateZ(0) 或者 will-change),
将渲染层提升为合成层,开启 GPU 加速,提高页面性能。 - tip: GPU加速是什么
又叫CSS3硬件加速,是利用GPU进行渲染,减少CPU操作的一种优化方案。由于CSS中的某些属性(如transform)不会触发repaint,所以能够提高网页性能。
比如,同样的DIV移动效果,用js操作DOM 改变left,top和CSS transform相比,transform更加流畅不掉帧,前者会出现轻微闪动(因为元素在不停的repaint)。
在 GPU 渲染的过程中,一些元素会因为符合了某些规则,而被提升为独立的层,那么就不会影响其它 DOM 的布局。利用这些规则,将经常变换的 DOM 主动提升到独立的层,即可减少paint和layout的时间。 - 创建独立图层
- transform
- opacity
- filter
- CSS
- TCP四次挥手断开连接
第一次挥手:主动方向被动方发送报文,Fin、Ack、Seq,表示已经没有数据传输了。并进入 FIN_WAIT_1 状态。
第二次挥手:被动方发送报文,Ack、Seq,表示同意关闭请求。此时主机主动方进入 FIN_WAIT_2 状态。
第三次挥手:被动方向主动方发送报文段,Fin、Ack、Seq,请求关闭连接。并进入 LAST_ACK 状态。
第四次挥手:主动方向被动方发送报文段,Ack、Seq。然后进入等待 TIME_WAIT 状态。被动方收到主动方的报文段以后关闭连接。主动方等待一定时间(2msl)未收到回复,则正常关闭。
七、 cookie localStorage sessionStorage
cookie是客户端保存用户信息的一种机制,用来记录用户信息,实际上是一小段的文本信息。
cookie 机制
客户端发送一个请求给服务器
服务器发送一个Response Headers给客户端,其中包含Set-Cookie的头部
客户端保存cookie,之后向服务器发送请求时,Request Headers中会包含一个Cookie的头部
服务器返回响应数据
tips:
修改cookie: 同名的Cookie来覆盖原先的Cookie
删除cookie: 新建一个同名的Cookie,并将maxAge设置为0,覆盖原来的
cookie 属性项
NAME=VALUE
Expires: 过期时间,在设置的某个时间点后该 Cookie 就会失效
Cookie中的maxAge用来表示该属性,单位为秒。
当maxAge属性为负数,表示该Cookie是一个临时Cookie,不会被持久化,仅在本浏览器窗口或者本窗口打开的子窗口中有效,关闭浏览器后该Cookie立即失效。
当maxAge为0时,表示立即删除CookieDomain: Cookie是不可以跨域名的
正常情况下,同一个一级域名下的两个二级域名也不能交互使用Cookie。
如果想要bar.com名下的二级域名都可以使用该Cookie,需要设置Cookie的domain参数为.bar.com,这样使用test1.bar.com和test2.bar.com就能访问同一个cookie
Session
session是一种记录客户状态的机制,保存在服务器上。为防止内存溢出,服务器会把长时间内没有活跃的session从内存中删除。
session工作机制:
session需要使用cookie作为识别标志。服务器向客户端浏览器发送一个名为SESSIONID的cookie,它的值为该Session的id,Session依据该cookie来识别是否为同一用户。
若浏览器禁用cookie,另一种解决方案:URL地址重写。该用户session的id信息重写到URL地址中,服务器解析后从URL获取session的id,来记录用户状态。
localStorage
localStorage 是 HTML5 提供的一个 API,可以用来保存本地的一些数据,不会因为刷新而释放。
localStorage生命周期是永久,意味着除非用户清除localStorage信息,否则这些信息将永远存在。
存放数据大小为一般为5MB,而且它仅在客户端中保存,不参与和服务器的通信。
只有相同域名的页面才能互相读取 localStorage,同源策略与 cookie 一致
sessionStorage
sessionStorage 的所有性质基本上与 localStorage 一致,唯一的不同区别在于:
sessionStorage 的有效期是页面会话持续,如果页面会话(session)结束(关闭窗口或标签页),sessionStorage 就会消失。而 localStorage 则会一直存在。
比较localStorage 和 sessionStorage
sessionStorage用于存储当前会话的数据,数据在页面会话结束时会被清除。
页面会话在浏览器打开期间一直保持,重新加载或恢复页面仍会保持原来的页面会话。
localStorage除非用户人为清除(调用 localStorage api 或则清除浏览器数据), 否则数据将被长期保留。
- 作用域不同
localStorage: 在同一个浏览器内,同源文档之间共享 localStorage 数据,可以互相读取、覆盖、清除 (同浏览器限制、同源限制)
sessionStorage: 与 localStorage 一样,需要同一浏览器同源文档这一条件。此外, sessionStorage 的作用域还被限定在了窗口中,
即 只有同一浏览器、同一窗口的同源文档才能共享数据 (同浏览器限制、同源限制、同标签页限制)
都有同源策略限制,跨域无法访问
| 特性 | cookie | localStorage | sessionStorage |
|---|---|---|---|
| 数据生命周期 | 一般由服务器生成,可设置失效时间。如果在浏览器端生成Cookie,默认是关闭浏览器后失效 | 除非被清除,否则永久保存 | 仅在当前会话下有效,关闭页面或浏览器后被清除 |
| 数据大小 | 4kb or so | 5MB | 5MB |
| 与服务器通信 | 每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 | 仅保存在客户端,不与服务器通信 | 仅保存在客户端,不与服务器通信 |
八、HTTP/2 和 HTTP/1.1 的对比
HTTP/1.1
- 相较于 HTTP/1.0 的改进和优化:
持久连接
在 HTTP/1.0 时期,每进行一次 HTTP 通信,都需要经过 TCP 三次握手建立连接。
若一个页面引用了多个资源文件,就会极大地增加服务器负担,拉长请求时间,降低用户体验。
HTTP/1.1 中增加的持久连接,可以在一次 TCP 连接中,发送和接收多个 HTTP 请求/响应。
只要浏览器和服务器没有明确断开连接,那么该 TCP 连接会一直保持下去。
持久连接在 HTTP/1.1 中默认开启(请求头中带有 Connection: keep-alive)新增 Host 头处理
在 HTTP/1.0 中认为每台服务器都绑定一个唯一的 IP 地址,因此一台服务器也无法搭建多个 Web 站点。
在 HTTP/1.1 中新增了 host 字段,可以指定请求将要发送到的服务器主机名和端口号。断点续传、并行下载
在 HTTP/1.1 中,新增了请求头字段 Range 和响应头字段 Content-Range。
前者是用来告知服务器应该返回文件的哪一部分,
后者则是用来表示返回的数据片段在整个文件中的位置。
可以借助这两个字段实现断点续传和并行下载。
- HTTP/1.1 的缺点:
队头阻塞
虽然在 HTTP1.1 中增加了持久连接,能在一次 TCP 连接中发送和接收多个 HTTP 请求/响应,
但是在一个管道中同一时刻只能处理一个请求,所以如果上一个请求未完成,后续的请求都会被阻塞。头部冗余
HTTP 请求每次都会带上请求头,若此时 cookie 也携带大量数据时,就会使得请求头部变得臃肿。TCP 连接数限制
浏览器对于同一个域名,根据浏览器内核的差异,只允许同时存在若干个 TCP 连接,若超最大连接数限制,后续请求就会被阻塞。
HTTP/2
- 优点:
多路复用
HTTP/2 允许在单个 TCP 连接上并行地处理多个请求和响应,真正解决了 HTTP/1.1 的队头阻塞和 TCP 连接数限制问题。Header 压缩
使用 HPACK 算法来压缩头部内容,包体积缩小,在网络上传输变快。服务端推送
允许服务端主动向浏览器推送额外的资源。
例如客户端请求 HTML 文件时,服务端可以同时将 JS 和 CSS 文件发送给客户端。二进制分帧层
在 HTTP/1.x 中,传输数据使用的是纯文本形式的报文,需不断读入字节,直到遇到分隔符为止。
而 HTTP/2 则是采用二进制编码,将请求和响应数据分割为一个或多个的体积小的帧。
- 本文作者:JSZ
- 本文链接:blog.vampuck.com/2023/02/04/http/index.html
- 版权声明:本博客所有文章均采用 BY-NC-SA 许可协议,转载请注明出处!