HTTP重点知识汇总
https://www.nowcoder.com/discuss/634359?channel=-1&source_id=profile_follow_post_nctrack
HTTP 1.0规定浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接,服务器完成请求处理后立即断开TCP连接。
设置http的headerconnection:Keep-Alive
HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
在http1.1中,client和server都是默认对方支持长链接的, 如果client使用http1.1协议,但又不希望使用长链接,则需要在header中指明connection的值为close;如果server方也不想支持长链接,则在response中也需要明确说明connection的值为close。不论request还是response的header中包含了值为close的connection,都表明当前正在使用的tcp链接在当天请求处理完毕后会被断掉。以后client再进行新的请求时就必须创建新的tcp链接了。
keep-alive的优点:
在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
网络延迟问题主要由于队头阻塞(Head-Of-Line Blocking),导致带宽无法被充分利用。
队头阻塞是指当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一并被阻塞,会导致客户端迟迟收不到数据。
TCP长连接复用(客户端阻塞): 一个请求响应完毕后,下一个请求才能发送,如果请求阻塞了,后面的请求都会受影响。(请求-响应、请求-响应 串行方式使用TCP长连接)
考虑pipeline的TCP长连接复用(服务端阻塞): 一个请求发送完毕后,无需等待响应,便可发送下一个请求。但是服务端响应的时候只能按照客户端发送请求的顺序进行响应,如果第一个请求处理特别慢,后面的请求即使处理完毕,也要等着。
造成队头阻塞有两个场景:
第一个场景:服务器处理一个请求太慢,这样,即使用pipeline模式把第二个请求也发送过去了,第二个请求比第一个请求先ready了,这个响应也不能发送,需要等到第一个完成后才行。这时候如果有一个序号机制,可以把第二个先发出去,这样的确会快一些。
但是还有第二个场景。服务器响应不慢,但是第一个请求太大了,传输很慢。这样pipeline也还是有问题,第二个请求虽然很小,但是还是得等第一个传输完了,响应完了才行。这时候你的序号机制就没用了。
所以要想让这两个情况都能让第二个请求不被第一个请求阻塞,最好的办法就是来两个TCP连接。传统上浏览器也是这么干的。但是TCP要握手,这个效率低,所以HTTP2把多个这种请求流塞到一个TCP连接里面,这样的连接复用方式就提高了效率,又节省了连接握手。
无状态是指协议对于连接状态没有记忆能力。纯净的 HTTP 是没有 cookie 等机制的,每一个连接都是一个新的连接。上一次请求验证了用户名密码,而下一次请求服务器并不知道它与上一条请求有何关联,换句话说就是掉登录态。
由于报文Header一般会携带"User Agent"“Cookie”“Accept”"Server"等许多固定的头字段,多达几百字节甚至上千字节,但Body却经常只有几十字节(比如GET请求、204/301/304响应)。Header里携带的内容过大,在一定程度上增加了传输的成本。更要命的是,成千上万的请求响应报文里有很多字段值都是重复的,非常浪费。
HTTP/1.1在传输数据时,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份,这在一定程度上无法保证数据的安全性。
HTTP/2传输数据量的大幅减少,主要有两个原因:以二进制方式传输和Header 压缩。HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。
首先,HTTP2 没有改变 HTTP1 的语义,只是在应用层使用二进制分帧方式传输。因此,也引入了新的通信单位:帧、消息、流。
帧:HTTP/2 数据通信的最⼩单位消息:指 HTTP/2 中逻辑上的 HTTP 消息。例如请求和响应等,消息由⼀个或多个帧组成。
流:存在于连接中的⼀个虚拟通道。流可以承载双向消息,每个流都有⼀个唯⼀的整数ID
分帧有什么好处?服务器单位时间接收到的请求数变多,可以提高并发数。最重要的是,为多路复用提供了底层支持。
HTTP消息分解为多个独立帧之后,这些帧可以交错和传输顺序,进一步提升性能。
使用专门的 HPACK 算法,每次请求和响应只发送差异头部,一般可以达到 50%~90% 的高压缩率。
每个 HTTP 传输都承载一组标头,这些标头说明了传输的资源及其属性。 在 HTTP/1.x 中,此元数据始终以纯文本形式,通常会给每个传输增加 500–800 字节的开销。如果使用 HTTP Cookie,增加的开销有时会达到上千字节。 (请参阅测量和控制协议开销。) 为了减少此开销和提升性能,HTTP/2 使用 HPACK 压缩格式压缩请求和响应标头元数据,这种格式采用两种简单但是强大的技术:
HTTP2.0在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键值对,对于相同的数据,不再通过每次请求和响应发送; 首部表在HTTP2.0的连接存续期内始终存在,由客户端和服务器共同更新; 每个新的首部键值对要么被追加到当前表的末尾,要么替换表中之前的值。
于是,HTTP2.0连接的两端都知道已经发送了哪些首部。请求与响应首部的定义在HTTP2.0中基本没有改变,只是所有的首部健必须全部小写。
HTTP/2 中,同域名下所有通信都在单个连接上完成,该连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装。多个请求可同时在一个连接上并行执行。某个请求任务耗时严重,不会影响到其它连接的正常执行;
一个域名对应一个连接,一个流代表了一个完整的请求-响应过程。帧是最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流。多路复用,就是在一个 TCP 连接中可以存在多个流。
出于兼容的考虑,HTTP/2延续了HTTP/1的“明文”特点,可以像以前一样使用明文传输数据,不强制使用加密通信,不过格式还是二进制,只是不需要解密。
但由于HTTPS已经是大势所趋,所以“事实上”的HTTP/2是加密的。也就是说,互联网上通常所能见到的HTTP/2都是使用"https”协议名。
支持使用 HTTPS 进行加密传输。
服务端推送是一种在客户端请求之前发送数据的机制。
HTTP2还在一定程度上改变了传统的“请求-应答”工作模式,服务器不再是完全被动地响应请求,也可以新建“流”主动向客户端发送消息。比如,在浏览器刚请求HTML的时候就提前把可能会用到的JS、CSS文件发给客户端,减少等待的延迟,这被称为"服务器推送"( Server Push,也叫 Cache push)
HTTP2支持在一个TCP连接中同时传输多个请求,服务器用一个TCP连接就能处理多个请求。复杂度更大,对SSL加密强依赖。而且丢包时重传会影响到这个TCP连接中的所有请求,也就是网络不好时性能不稳定,不如HTTP1可靠。
HTTP/2都是使用TCP协议来传输的,而如果使用HTTPS的话,还需要使用TLS协议进行安全传输,而使用TLS也需要一个握手过程,这样就需要有两个握手延迟过程:
①在建立TCP连接的时候,需要和服务器进行三次握手来确认连接成功,也就是说需要在消耗完1.5个RTT之后才能进行数据传输。
②进行TLS连接,TLS有两个版本——TLS1.2和TLS1.3,每个版本建立连接所花的时间不同,大致是需要1~2个RTT。
总之,在传输数据之前,我们需要花掉 3~4 个 RTT。
TCP 为了保证可靠传输,有一个“超时重传”机制,丢失的包必须等待重传确认。HTTP2 出现丢包时,整个 TCP 都要等待重传,那么就会阻塞该 TCP 连接中的所有请求,那么就会阻塞该TCP连接中的所有请求。
需要注意HTTP2没有完全解决队头阻塞问题,因为实际中TCP的连接buffer有限,一个响应又慢,又大的请求会把链接buffer完全占满,导致buffer阻塞,从而导致跟队头阻塞一样的效果。
TCP的应答是严格有序的,如果前面的包没到,即使后面的到了也不能应答,这样可能会导致后面的包被重传,窗口被“阻塞”在队首,这就是传输层的队首阻塞。 不管是HTTP/1.1还是HTTP/2,在传输层都是基于TCP,那么TCP层的队首阻塞问题都是存在的
多路复用没有限制同时请求数。请求的平均数量与往常相同,但实际会有许多请求的短暂爆发,导致瞬时 QPS 暴增。
大批量的请求同时发送,由于 HTTP2 连接内存在多个并行的流,而网络带宽和服务器资源有限,每个流的资源会被稀释,虽然它们开始时间相差更短,但却都可能超时。
由于 QUIC 是基于 UDP 的,而UDP是“无连接”的,根本就不需要“握手”和“挥手”,所以就比TCP来得快。所以 QUIC 可以实现 0-RTT 或者 1-RTT 来建立连接,可以大大提升首次打开页面的速度。0RTT 建连可以说是 QUIC 相比 HTTP2 最大的性能优势。
基于 UDP,就可以在 QUIC 自己的逻辑里面维护连接的机制,不再以四元组标识,而是以一个 64 位的随机数作为 ID 来标识,而且 UDP 是无连接的,所以当 IP 或者端口变化的时候,只要 ID 不变,就不需要重新建立连接。
虽然UDP不提供可靠性的传输,但QUIC在UDP的基础之上增加了一层来保证数据可靠性传输。它提供了数据包重传、拥塞控制以及其他一些TCP中存在的特性。
QUIC 定义了一个 offset 概念。 QUIC 既然是面向连接的,也就像 TCP 一样,是一个数据流,发送的数据在这个数据流里面有个偏移量 offset,可以通过 offset 查看数据发送到了哪里,这样只要这个 offset 的包没有来,就要重发;如果来了,按照 offset 拼接,还是能够拼成一个流。
而 QUIC 则采用一种更主动的方案,有点类似 RAID5 ,每 n 个包额外发一个 校验和包 。 如果这 n 个包中丢了一个包,可以通过其他包和校验和恢复出来,完全不需要重传。
集成了TLS加密功能。目前QUIC使用的是TLS1.3,相较于早期版本TLS1.3有更多的优点,其中最重要的一点是减少了握手所花费的RTT个数。
QUIC 是为多路复用从头设计的,携带个别流的的数据的包丢失时,通常只影响该流。QUIC 连接上的多个 stream 之间并没有依赖,也不会有底层协议限制。假如 stream2 丢了一个包,也只会影响 stream2 的处理。stream2 丢了一个 UDP 包,后面跟着 stream3 的一个 UDP 包,虽然 stream2 的那个包需要重传,但是 stream3 的包无需等待,就可以发给用户。
和TCP不同,QUIC实现了在同一物理连接上可以有多个独立的逻辑数据流。实现了数据流的单独传输,就解决了TCP中队头阻塞的问题。
QUIC一个connection可以复用传输多个stream,每个stream之间都是独立的,一个stream的丢包不会影响到其他stream的接收和处理。
HTTP/1.1有两个主要的缺点:安全不足(明文传输)和性能不高(高延迟,无状态特性)。
HTTP/2完全兼容HTTP/1,是“更安全的HTTP/1、更快的HTTPS",头部压缩、多路复用等技术可以充分利用带宽,降低延迟,从而大幅度提高上网体验;
QUIC 基于 UDP 实现,是 HTTP/3 中的底层支撑协议,该协议基于 UDP,又取了 TCP 中的精华(流量控制,可靠传输),集成了TLS加密功能,实现了即快又可靠的协议。
HTTPS其实是有两部分组成:HTTP +SSL/ TLS,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。
SSL: 安全套接层(Secure Sockets Layer)
TLS: 传输层安全性协议(Transport Layer Security)
HTTPS协议需要到证书颁发机构(Certificate Authority,简称CA)申请证书,一般免费证书很少,需要交费。
HTTP是超文本传输协议,信息是明文传输,HTTPS则是具有安全性的SSL加密传输协议。
HTTP和HTTPS使用的是完全不同的连接方式,使用的端口也不一样,前者是80,后者是443。
HTTP的连接很简单,是无状态的。
HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比HTTP协议安全。
从上面可看出,HTTPS和HTTP协议相比提供了
数据完整性:内容传输经过完整性校验
数据隐私性:内容经过对称加密,每个连接生成一个唯一的加密密钥
身份认证:第三方无法伪造服务端(客户端)身份
其中,数据完整性和隐私性由TLS Record Protocol保证,身份认证由TLS Handshaking Protocols实现。
对称加密算法加密数据+非对称加密算法交换密钥+数字证书验证身份=安全
数字签名就是⽤CA⾃带的HASH算法对证书的内容进⾏HASH得到⼀个摘要,再⽤CA的私钥加密,最终组成数字签名。
当别⼈把他的证书发过来的时候,我再⽤同样的Hash算法,再次⽣成消息摘要,然后⽤CA的公钥对数字签名解密,得到CA创建的消息摘要,两者⼀⽐,就知道中间有没有被⼈篡改了。
为了解决此问题,我们引入了数字证书的概念。
服务器首先生成公私钥,将公钥提供给相关机构(CA),CA将公钥放入数字证书并将数字证书颁布给服务器,此时服务器就不是简单的把公钥给客户端,而是给客户端一个数字证书,数字证书中加入了一些数字签名的机制,保证了数字证书一定是服务器给客户端的。
而中间人发送的伪造证书,不能够获得CA的认证,此时,客户端和服务器就知道通信被劫持了。加入了CA数字签名认证的SSL会话过程如下所示:
客户端发起 HTTPS 请求
建立TCP连接之后,客户端发起请求
服务端的配置
服务端收到请求之后,会有一套公钥和私钥,这对公钥和私钥其实就是一套数字证书,一般都是由受信任的证书颁发机构进行签发。
传送公钥
服务端将公钥传递给客户端,里面包含很多信息,如证书的颁发机构,证书的过期时间
客户端解析证书
这部分工作由客户端的 TSL 来完成,首先验证证书是否有效。如果没有问题,就会随机生成一个 key,然后利用公钥对 key 的值进行加密。
传送加密的信息(key)
加密过后的 key 传递给服务器
使用私钥解析加密信息(key)
服务器使用自己的私钥解密加密信息得到 key
使用客户端的 key,利用对称加密加密信息,并发送给客户端
把内容通过该 key 进行对称加密,并传输给客户端
客户端使用 key 解密信息
客户端收到信息之后利用 key 进行解密
重点: 客户端会生成 key,key 的传输使用非对称加密,而数据的传输使用 key 进行对称加密。
对称加密:加密密钥和解密密钥是同一个,效率较高
非对称加密:加密密钥和解密密钥不是同一个,效率较低
所以综合以上三点:非对称加密算法(公钥和私钥)交换对称密钥 + 数字证书验证身份(验证公钥是否是伪造的) + 利用对称密钥加解密后续传输的数据 = 安全
由于非对称加密的效率比较低,因此我们通常不使用非对称加密对整个文件进行加密,而采用对称加密对文件加密,非对称加密对对称加密的密钥加密,然后将对称加密后的文件和非对称加密后的密钥一起在网上传送。
详解 HTTPS、TLS、SSL、HTTP区别和关系
第一,检查SSL 证书是否是由浏览器中“受信任的根证书颁发机构”颁发,如果不是,则浏览器会有安全警告。
第二,检查SSL证书中的证书吊销列表,检查证书是否被证书颁发机构吊销?如果已经被吊销,则会显示警告信息。
第三,检查此SSL证书是否过期?如果证书已经过了有效期,则会显示警告信息。
第四,检查部署此SSL证书的网站的域名是否与证书中的域名一致?如果不一致,则浏览器也会显示警告信息。
第五,IE7浏览器会到欺诈网站数据库查询此网站是否已经被列入欺诈网站黑名单。
状态码分类表
类别 | 原因 | 短语 |
---|---|---|
1xx | Informational(信息性状态码) | 接受的请求正在处理 |
2xx | Success(成功状态码) | 请求正常处理完毕 |
3xx | Redirection(重定向) | 需要进行附加操作以完成请求 |
4xx | Client Error(客户端错误) | 客户端请求出错,服务器无法处理请求 |
5xx | Server Error(服务器错误) | 服务器处理请求出错 |
各类别常见状态码:
200 OK:表示从客户端发送给服务器的请求被正常处理并返回;
201 Created :请求已经被实现,⽽且有⼀个新的资源已经依据请求的需要⽽建⽴
202 Accepted :请求已接受,但是还没执⾏,不保证完成请求
204 No Content:表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回);
206 Patial Content:表示客户端进行了范围请求,并且服务器成功执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容。
301 Moved Permanently:永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;
302 Found:临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL;
301与302的区别:前者是永久移动,后者是临时移动(之后可能还会更改URL)
303 See Other:表示请求的资源被分配了新的URL,应使用GET方法定向获取请求的资源;明确表示客户端应当采⽤get⽅法获取资源,他会把POST请求变为GET请求进⾏重定向。
302与303的区别:后者明确表示客户端应当采用GET方式获取资源
304 Not Modified:表示客户端发送附带条件(是指采用GET方法的请求报文中包含if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任一首部)的请求时,服务器端允许访问资源,但是请求为满足条件的情况下返回改状态码;
307 Temporary Redirect:临时重定向,与303有着相同的含义,307会遵照浏览器标准不会从POST变成GET;(不同浏览器可能会出现不同的情况);
400 Bad Request:表示请求报文中存在语法错误;
401 Unauthorized:未经许可,需要通过HTTP认证;
403 Forbidden:服务器拒绝该次访问(访问权限出现问题)
404 Not Found:表示服务器上无法找到请求的资源,除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;
408 Request timeout:客户端请求超时
409 Confict:请求的资源可能引起冲突
500 Inter Server Error:表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误;
501 Not Implemented :服务器不支持请求的功能,无法完成请求
503 Server Unavailable:表示服务器暂时处于超负载或正在进行停机维护,无法处理请求;
505 http version not supported :服务器不⽀持,或者拒绝⽀持在请求中使⽤的 HTTP 版本
图解HTTP(六)—— HTTP请求头(首部)
HTTP常见首部含义
Http Headers各属性的作用
(1)application/x-www-form-urlencoded
这是浏览器原生的form表单类型,或者说是表单默认的类型。
(2)application/json
现在绝大部分的请求都会以json形式进行传输,post会将序列化后的json字符串直接塞进请求体中。
(3)multipart/form-data
用于在表单中上传文件
常见的媒体格式类型如下:
text/html : HTML格式
text/plain :纯文本格式
text/xml : XML格式
image/gif :gif图片格式
image/jpeg :jpg图片格式
image/png:png图片格式
以application开头的媒体格式类型:
application/xhtml+xml :XHTML格式
application/xml : XML数据格式
application/atom+xml :Atom XML聚合格式
application/json : JSON数据格式
application/pdf :pdf格式
application/msword : Word文档格式
application/octet-stream : 二进制流数据(如常见的文件下载)
application/x-www-form-urlencoded : 中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)
另外一种常见的媒体格式是上传文件之时使用的:
multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式
Http Headers各属性的作用
HTTP常见首部含义
HTTP1.0定义了三种请求方法: GET、POST 和 HEAD方法。
HTTP1.1新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。
GET
GET 是最常用的方法。通常用于请求服务器发送某个资源。HTTP/1.1 要求服务器实现此方法。GET方法不应有副作用,所以是幂等的。
GET请求长度:
Http get方法提交的数据大小长度并没有限制,Http协议规范没有对URL长度进行限制。
目前说的get长度有限制,是特定的浏览器及服务器对它的限制。
HEAD
HEAD 方法与 GET 方法的行为很类似,但服务器在响应中只返回首部,不会返回实体的主体部分。这就允许客户端在未获取实际资源的情况下,对资源的首部进行检查。
该请求⽅法的⼀个使⽤场景是在下载⼀个⼤⽂件前先获取其⼤⼩再决定是否要下载, 以此可以节约带宽资源
POST
POST 方法起初是用来向服务器输入数据的。实际上,通常会用它来支持 HTML 的表单。表单中填好的数据通常会被送给服务器,然后由服务器将其发送到它要去的地方。POST所对应的URI并非创建的资源本身,而是资源的接收者。POST方法不具备幂等性。
理论上讲,post是没有大小限制的。Http协议规范也没有进行大小限制,起限制作用的是服务器处理程序的处理能力。
除此之外还有⼀个区别,通常情况下,PUT的URI指向是具体单⼀资源,⽽POST可以指向资源集合。
举个例⼦,我们在开发⼀个博客系统,当我们要创建⼀篇⽂章的时候往往⽤ POST https://www.jianshu.com/articles , 这个请求的语义是,在articles的资源集合下创建⼀篇新的⽂章,如果我们多次提交这个请求会创建多个⽂章,这是⾮幂等的。
⽽ PUT https://www.jianshu.com/articles/820357430 的语义是更新对应⽂章下的资源(⽐如修改作者名称等),这个 URI指向的就是单⼀资源,⽽且是幂等的。
PUT
与 GET 从服务器读取文档相反,PUT 方法会向服务器写入文档。PUT 方法的语义就是让服务器用请求的主体部分来创建一个由所请求的 URL 命名的新文档,或者,如果那个 URL 已经存在的话,就用这个主体来替代它。 PUT所对应的URI是要创建或更新的资源本身。比如:PUT http://www.forum/articles/4231的语义是创建或更新ID为4231的帖子。对同一URI进行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有幂等性。
PATCH
PATCH请求与PUT请求类似,同样用于资源的更新。二者有以下两点不同:
DELETE
顾名思义,DELETE 方法所做的事情就是请服务器删除请求 URL 所指定的资源。有副作用,但它应该满足幂等性。比如:DELETE http://www.forum.com/article/4231,调用一次和N次对系统产生的副作用是相同的,即删掉id为4231的帖子;因此,调用者可以多次调用或刷新页面而不必担心引起错误。
CONNECT
CONNECT方法是HTTP/1.1协议预留的,能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接与非加密的HTTP代理服务器的通信。
OPTIONS
OPTIONS 方法请求 Web 服务器告知其支持的各种功能。可以询问服务器通常支持哪些方法,或者对某些特殊资源支持哪些方法,一般是客户端向服务端判断对某个资源是否有访问权限。。客户端通过该方法可以在不访问服务器上实际资源的情况下就知道处理该资源的最优方式。
预检请求过程:
CONNECT: HTTP/1.1协议中预留给能够将连接改为管道⽅式的代理服务器
TRACE: 回显服务器收到的请求,主要⽤于测试或诊断
简单请求必须符合以下规定:
只能使用get/post/head请求方式
不能手动设置以下集合之外的请求头信息
content-type只能设置以下内容(Content-Type一般是指在post请求中,get请求中设置没有实际意义):
不能为XMLHttpRequestUpdate注册监听器
请求中没有使用readableStream对象
非简单请求的都是复杂请求
1、首先即使有长度限制,也是限制的是整个URI长度,而不仅仅是你的参数值数据长度。
2、HTTP协议从未规定GET/POST的请求长度限制是多少
3、所谓的请求长度限制是由浏览器和web服务器决定和设置的,浏览器和web服务器的设定均不一样,
这依赖于各个浏览器厂家的规定或者可以根据web服务器的处理能力来设定。
从定义上看,HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。说白了就是,同一个请求,发送一次和发送N次效果是一样的!
在浏览器第一次发出请求之后,需要再次发送请求的时候,浏览器首先获取该资源缓存的 header 信息,然后根据 Cache-Control
和 Expires
字段判断缓存是否过期。如果没有过期,直接使用浏览器缓存,并不会与服务器通信。该过程为判断是否使用强缓存,即本地缓存。
Cache-Control
字段是 HTTP1.1 规范,一般利用该字段的 max-age 属性来判断,这个值是一个相对时间,单位为 s,代表资源的有效期。例如:Cache-Control:max-age=3600
除此之外还有几个常用的值:
Expires
字段是 HTTP1.0 规范,他是一个绝对时间的 GMT 格式的时间字符串。例如:expires:Mar, 06 Apr 2020 10:57:09 GMT
这个时间代表资源的失效时间,只要发送请求的时间在这之前,都会使用强缓存。
由于失效时间是一个绝对时间(本地时间),因此当服务器时间与客户端时间偏差较大时,就会导致缓存混乱。
值得注意的是expires时间可能存在客户端时间跟服务端时间不一致的问题。所以,建议expires结合Cache-Control一起使用
而Cache-Control的max-age是一个相对时间,消除了服务器时间和客户端时间偏差带来的问题。
当第⼀次请求时服务器返回的响应头中没有Cache-Control和Expires或者Cache-Control和Expires过期抑或它的属性设置为no-cache时,那么浏览器会向服务器发送请求,即使用协商缓存。本次请求会带着第一次请求返回的有关缓存的 header 字段信息,比如以下两个字段:
Etag/If-None-Match
ETag是响应头,If-None-Match是请求头。
Last-Modified / If-Modified-Since的主要缺点就是它只能精确到秒的级别,一旦在一秒的时间里出现了多次修改,那么Last-Modified / If-Modified-Since是无法体现的。
相比较,ETag / If-None-Match没有使用时间作为判断标准,而是使用一个特征串。Etag把Web组件的特征串告诉客户端,客户端在下次请求此Web组件的时候,会把上次服务端响应的特征串作为If-None-Match的值发送给服务端,服务端可以通过这个值来判断是否需要从重新发送,如果不需要,就简单的发送一个304状态码,客户端将从缓存里直接读取所需的Web组件。
判断响应头中是否存在 Etag 字段,如果存在,浏览器则发送一个带有 If-None-Match
字段的请求头的请求,该字段的值为 Etag
值。服务器通过对比客户端发过来的Etag值是否与服务器相同。如果相同,说明缓存命中,服务器返回 304 状态码,并将 If-None-Match
设为 false
, 客户端继续使用本地缓存。如果不相同,说明缓存未命中,服务器返回 200 状态码,并将 If-None-Match
设为 true
,并且返回请求的数据。
Last-Modified/If-Modified-Since
Last-Modified是响应头,If-Modified-Since是请求头。
Last-Modified把Web组件的最后修改时间告诉客户端,客户端在下次请求此Web组件的时候,会把上次服务端响应的最后修改时间作为If-Modified-Since的值发送给服务器,服务器可以通过这个值来判断是否需要重新发送,如果不需要,就简单的发送一个304状态码,客户端将从缓存里直接读取所需的Web组件。
除了 Etag
字段之外,客户端还会通过服务器返回的 Last-Modified
字段判断是否继续使用缓存,该字段为服务器返回的资源的最后修改时间,为UMT时间。浏览器发送一个带有 If-Modified-Since
字段的请求头的请求给服务器,该字段的值为 Last-Modified
值。服务器收到之后,通过这个时间判断,在该时间之后,资源有无修改,如果未修改,缓存命中,返回 304 状态码;如果未命中,返回 200 状态码,并返回最新的内容。
Etag缺点:分布式系统上需要关闭Etag,因为每台机器上生成的Etag都不一样
Cache-Control
与 Expires
的优先级:两者可以在服务端配置同时使用,Cache-Control 的优先级高于 Expires。
Last-Modified/If-Modified-Since 已经可以判断缓存是否失效了,为什么出现 Etag/If-None-Match?
Etag/If-None-Match 是实体标签,是一个资源的唯一标识符,资源的变化都会导致 ETag 的变化。出现 Etag 的主要原因是解决 Last-Modified 比较难解决的问题:
Last-Modified 和 Etag 可以一起使用, Etag 的优先级更高。
刷新页面的问题:
F5刷新:不使用强缓存,使用协商缓存
ctrl+F5:二者都不使用
所以,当浏览器请求的是一个静态资源时,即服务器能明确知道返回内容的长度时,可以设置Content-Length
来控制请求的结束。但当服务器并不知道请求结果的长度时,如一个动态的页面或者数据,Content-Length
就无法解决上面的问题,这个时候就需要用到Transfer-Encoding
字段。
Content-Encoding
。区别是Content-Encoding
用于对实体内容的压缩编码(Content-Encoding: gzip); Transfer-Encoding
则改变了报文的格式。Transfer-Encoding:chunked
(还可同时指定Content-Encoding: gzip
),表明实体内容数据不仅是gzip压缩的,还是分块传递的。 最终当浏览器接收到一个长度为0的chunked时, 标识当前请求内容已全部接收。websocket 用途,例子,场景,什么时候用websocket
Websocket是HTML5新增的一种全双工通信协议,客户端和服务端基于TCP握手连接成功后,两者之间就可以建立持久性的连接,实现双向数据传输。
WebSocket 是一个全新的、独立的协议,基于 TCP 协议,与 HTTP 协议兼容却不会融入 HTTP 协议,仅仅作为 HTML5 的一部分。
WebSocket 是一种协议,是一种与 HTTP 同等的网络协议,两者都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。
传统HTTP和Websocket的异同
- 不同点:
- HTTP是单向数据流,客户端向服务端发送请求,服务端响应并返回数据;Websocket连接后可以实现客户端和服务端双向数据传递,都能主动的向对方发送或接收数据。
- 由于是新的协议,HTTP的url使用"http//"或"https//"开头;Websocket的url使用"ws//"开头。
- 相同点
- 都需要建立TCP连接,同http一样通过TCP来传输数据
都是属于七层协议中的应用层协议
- 联系
WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的。
传统通过HTTP请求模拟双向数据传递的方式是http+Polling(轮询)和http+Long Polling(长轮询)。
(短)轮询(Polling)就是客户端定时发送get请求向服务端请求数据,服务器收到请求后,将最新的数据发回给 client,这种方式能满足一定的需求,但是存在一些问题,如果服务端没有新数据,但是客户端get请求到的数据都是旧数据,这样不仅浪费了带宽资源,而且占用CPU内存。
长轮询(Long Polling)就是在Polling上的一些改进,即如果服务端没有新数据返回给客户端,服务端会把当前的这个get请求保持住(hold),当有新数据时则返回新数据,如果超过一定时间服务端仍没有新数据,则服务端返回超时请求,客户端接收到超时请求,然后在发送get请求,一直循环执行。
虽然一定程度解决了带宽资源和CPU内存浪费情况,但是当服务端数据更新很快,这和轮询(Polling)没有本质上的区别,而且http数据包的头部数据量往往很大(通常有400多个字节),但是真正被服务器需要的数据却很少(有时只有10个字节左右),这样的数据包在网络上周期性的传输,难免对网络带宽是一种浪费。在高并发的情况下,这对服务器是一个很大的挑战。
一旦 WebSocket 连接建立后,除非 client 或者 server 中有一端主动断开连接,否则每次数据传输之前都不需要 HTTP 那样请求数据。从上面的图可以看出,client 第一次需要与 server 建立连接,当 server 确认连接之后,两者便一直处于连接状态。直到一方断开连接,WebSocket 连接才断开。
const ws = new WebSocket("ws//:xxx.xx", [protocol])
ws.onopen = () => {
ws.send('hello')
console.log('send')
}
ws.onmessage = (ev) =>{
console.log(ev.data)
ws.close()
}
ws.onclose = (ev) =>{
console.log('close')
}
ws.onerror = (ev) =>{
console.log('error')
}
在支持WebSocket的浏览器中,创建Socket之后,通过onopen、onmessage、onclose、onerror四个事件的实现来处理Socket的响应;
Websocket使用和 HTTP 相同的 TCP 端口,可以绕过大多数防火墙的限制。默认情况下,Websocket协议使用80端口;运行在TLS之上时,默认使用443端口。
Socket.IO 是一个封装了 Websocket、基于 Node 的 JavaScript 框架,包含 client 的 JavaScript 和 server 的 Node。其屏蔽了所有底层细节,让顶层调用非常简单。
另外,Socket.IO 还有一个非常重要的好处。其不仅支持 WebSocket,还支持许多种轮询机制以及其他实时通信方式,并封装了通用的接口。这些方式包含 Adobe Flash Socket、Ajax 长轮询、Ajax multipart streaming 、持久 Iframe、JSONP 轮询等。换句话说,当 Socket.IO 检测到当前环境不支持 WebSocket 时,能够自动地选择最佳的方式来实现网络的实时通信。 在使用SocketIO时,不用担心兼容问题,底层会自动选用最佳的通信方式。因此说,WebSocket是SocketIO的一个子集。