Open lznbuild opened 4 years ago
1XX 临时返回,表示客户端继续其请求,被浏览器HTTP库直接处理掉了,不会让上层应用知道
2XX 请求成功
3XX 表示请求的目标有变化,希望客户端进一步处理
301&302:永久性与临时性跳转。
304:跟客户端缓存没有更新。产生这个状态的前提是:客户端本地已经有缓存的版本,并且在 Request 中告诉了服务端,当服务端通过时间或者 tag,发现没有更新的时候,就会返回一个不含 body 的 304 状态
4xx:客户端请求错误。
403:无权限。
404:表示请求的资源不存在。
5xx:内部服务器错误
GET 参数通过 url 传递,POST 放在 body 中,POST相对安全
GET 请求在 url 中传递的参数是有长度限制的,而 POST 没有,长度限制来源于浏览器对地址栏输入内容的限制,非GET请求本身的限制
GET 在浏览器回退时是无害的(有缓存,协商缓存),而 POST 会再次提交请求,也就是说,GET 请求会被浏览器主动 cache,而 POST 不会,除非手动设置。
GET 请求只能进行 url(x-www-form-urlencoded)编码,而 POST 支持多种编码方式。
GET 产生一个 TCP 数据包;POST 产生两个 TCP 数据包。对于 GET 方式的请求,浏览器会把 http 的 header 和 data 一并发送出去,服务器响应200(返回数据)。而对于 POST,浏览器先发送 header,服务器响应100 continue,浏览器再发送 data,服务器响应200 ok(返回数据)
PUT是幂等的,连续调用一次或者多次的效果相同(无副作用), 如果两个请求相同,后一个请求会把第一个请求覆盖掉 (PUT更多的用来改资源)
POST是非幂等的方式,后一个请求不会把第一个请求覆盖掉(POST更多的用来增资源)
Cache-Control 控制缓存
Connection 设置为Keep-alive用于告诉客户端本次HTTP请求结束之后并不需要关闭TCP连接,这样可以使下次HTTP请求使用相同的TCP通道,节省TCP连接建立的时间。
Upgrade 升级为其他协议
via 代理服务器的相关信息
Transfor-Encoding 报文主体的传输编码格式
Pragma 报文指令
Date 创建报文的日期
origin:发起请求的服务器地址
Accept :客户端或者代理能够处理的媒体类型
Accept-Encoding 优先可处理的编码格式
Accept-Language 优先可处理的自然语言
Accept-Charset 优先可以处理的字符集
If-Match 比较实体标记(ETage)
If-None-Match 比较实体标记(ETage)与 If-Match相反
If-Modified-Since 比较资源更新时间(Last-Modified)
Authorization web的认证信息 ✨
Host 请求资源所在服务器 ✨
User-Agent 客户端程序信息 ✨
Referer 请求原始放的url
Location:令客户端重定向的URI
Last-Modified:该资源最后被修改的时间
set-cookie:设置cookie
content-length
content-type
date ETag
Expires
keep-alive
先大概说一下流程。
第一次握手,客户端发了个连接请求消息到服务端,服务端收到信息后知道自己与客户端是可以连接成功的,但此时客户端并不知道服务端是否已经接收到了它的请求。
第二次握手,服务端接收到消息后的应答,客户端得到服务端的反馈后,才确定自己与服务端是可以连接上的, 客户端只有确定了自己能与服务端连接上才能开始发数据。所以两次握手肯定是最基本的。
第三次握手,是为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误。如果没有第3次,服务器端是不知道客户端有没有接收到服务器端返回的信息,造成服务器端开销的严重浪费。
再归纳一下 每一步。
seq 序列号
ack 确认号,只有ACK为1时,它才有效, ack = seq+1
标志位
ACK: 确认序号有效 SYN: 发起一个新链接 FIN: 释放一个链接
第一次握手,客户端选择一个随机序列号seq(假设为x),并发送一个SYN数据包(1表示开启新连接,0结束连接),其中可能还包括其他TCP标志和选项,客户端将这个数据包给服务器请求连接。
第二次握手, 服务器用一个带有确认应答ACK(1)和同步序列号SYN(1),ack(x+1),seq(假设为y)的数据段,相应客户端,用来通知客户端,服务端已经收到SYN消息并通过了确认。
第三次握手,客户端笑了,说明,client发送给server,server发送给client都可以,但是server不知道这个整体流程走通了没,所以给ACK(1)seq(x+1),ack(y+1)发送握手期间的最后一个数据包,客户端收到数据后,发送数据段确认收到,服务器收到此数据确认无误,开始传送数据
其实第三次握手的时候,是可以携带数据的。但是,第一次、第二次握手不可以携带数据
TCP协议可以是一个全双工通信的,接收方和发起方都可以发送信息,要有一个序列号,表示那些是同一个请求过程中的。序列号也不能从0开始,会混淆的,相对随机生成的,TCP规范中也不允许连接一直是一个半打开的状态。
1.首先客户端想要释放连接,向服务器端发送一段TCP报文(连接释放报文),FIN=1,seq=x并停止发送数据
2.服务器端接收到从客户端发出的TCP报文之后,确认了客户端想要释放连接,随后服务器端进入一个半关闭的状态(不能一直持续),并返回一段TCP报文(确认报文) ACK=1,ack=x+1,seq=v
3.服务器端准备好后,再次向客户端发出一段TCP报文 FIN =1,ACK=1, seq=w, ack=x+1 关闭。
4.客户端收到从服务器端发出的TCP报文,确认了服务器端已做好释放连接的准备,再次传输一段报文 ACK=1,ack=w+1,seq=x+1
因为TCP是全双工通信,在关闭连接的时候,既要关闭客户端的连接,也要关掉服务端建立的连接,所以需要四次挥手
因为当服务端收到客户端的 FIN 报文后,发送的 ACK 报文只是用来应答的,并不表示服务端也希望立即关闭连接。
当只有服务端把所有的报文都发送完了,才会发送 FIN 报文,告诉客户端可以断开连接了,因此在断开连接时需要四次挥手。
TCP建立连接时之所以只需要"三次握手",是因为在第二次"握手"过程中,服务器端发送给客户端的TCP报文是以SYN与ACK作为标志位的。SYN是请求连接标志,表示服务器端同意建立连接;ACK是确认报文,表示告诉客户端,服务器端收到了它的请求报文。
即SYN建立连接报文与ACK确认接收报文是在同一次"握手"当中传输的,所以"三次握手"不多也不少,正好让双方明确彼此信息互通。
TCP释放连接时之所以需要“四次挥手”,是因为FIN释放连接报文与ACK确认接收报文是分别由第二次和第三次"握手"传输的。为何建立连接时一起传输,释放连接时却要分开传输?
建立连接时,被动方服务器端结束CLOSED阶段进入“握手”阶段并不需要任何准备,可以直接返回SYN和ACK报文,开始建立连接。 释放连接时,被动方服务器,突然收到主动方客户端释放连接的请求时并不能立即释放连接,因为还有必要的数据需要处理,所以服务器先返回ACK确认收到报文,经过CLOSE-WAIT阶段准备好释放连接之后,才能返回FIN释放连接报文。
所以是“三次握手”,“四次挥手”。
搜索浏览器自身的DNS缓存==> 操作系统的hosts文件==> 查找本地DNS服务器 ==> 根服务器 ==> 顶级服务器
用于获取目的资源所支持的通信选项。 响应报文包含一个 Allow 首部字段,该字段的值表明了服务器支持的所有 HTTP 方法
在 CORS 中,可以使用 OPTIONS 方法发起一个预检请求,以检测实际请求是否可以被服务器所接受。预检请求报文中的 Access-Control-Request-Method 首部字段告知服务器实际请求所使用的 HTTP 方法;Access-Control-Request-Headers 首部字段告知服务器实际请求所携带的自定义首部字段。服务器基于从预检请求获得的信息来判断,是否接受接下来的实际请求。
HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法。HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法
HTTP1.1中新增了很多错误状态响应码
HTTP 1.1支持长连接。
在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。通过设置http的请求头部和应答头部,保证本次数据请求结束之后,下一次请求仍可以重用这一通道,避免重新握手。原理是请求完成后不立即释放连接,而是放入连接池中,若这时有另一个请求要发出,请求的域名和端口是一样的,就直接拿出连接池中的连接进行发送和接收数据,少了建立连接的耗时。但有个问题,就是这个 keep-alive 的连接一次只能发送接收一个请求,在上一个请求处理完成之前,无法接受新的请求。
若同时发起多个请求,就有两种情况:若串行发送请求,可以一直复用一个连接,但速度很慢,每个请求都要等待上个请求完成再进行发送。
若并行发送这些请求,那么首次每个请求都要进行tcp三次握手建立新的连接,虽然第二次可以复用连接池里这堆连接,但若连接池里保持的连接过多,对服务端资源产生较大浪费,若限制了保持的连接数,并行请求里超出的连接仍每次要建连。
对这个问题,新一代协议 HTTP2 提出了多路复用去解决。
HTTP/2 采用二进制格式传输数据,解析更高效
多路复用,支持 TCP 连接复用
加密。
HTTPS 有两个作用,一是确定请求的目标服务端身份,二是保证传输的数据不会被网络中间节点窃听或者篡改。HTTPS 是使用加密通道来传输 HTTP 的内容。但是 HTTPS 首先与服务端建立一条 TLS 加密通道。TLS 构建于 TCP 协议之上,它实际上是对传输的内容做一次加密,所以从传输内容上看,HTTPS 跟 HTTP 没有任何区别。
HTTP2.0 支持服务端推送
服务端推送能够在客户端发送第一个请求到服务端时,提前把一部分内容推送给客户端,放入缓存当中,这可以避免客户端请求顺序带来的并行度不高,从而导致的性能问题。 服务端推送能把客户端所需要的资源伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度。例如我的网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了。
TCP 连接复用,则使用同一个 TCP 连接来传输多个 HTTP 请求,避免了 TCP 连接建立时的三次握手开销,和初建 TCP 连接时传输窗口小的问题。
在HTTP/1.1协议中,浏览器客户端在同一时间,针对同一域名下的请求有一定数量限制,超过限制数目的请求会被阻塞。(6个)所谓请求阻塞意思就是一条TCP的connection在同一时间只能允许一个请求经过,这样假如后续请求想要复用这个链接就必须等到前一个完成才行
HTTP/2多个请求可同时在一个连接上并行执行。某个请求任务耗时严重,不会影响到其它连接的正常执行,server端可以根据stream的唯一标识来相应对应的请求。HTTP2 的多路复用看起来是完美的解决方案,但还有个问题,就是队头阻塞,这是受限于 TCP 协议,TCP 协议为了保证数据的可靠性,若传输过程中一个 TCP 包丢失,会等待这个包重传后,才会处理后续的包。HTTP2的多路复用让所有请求都在同一条连接进行,中间有一个包丢失,就会阻塞等待重传,所有请求也就被阻塞了。这个问题无法解决,本身http协议就是基于TCP协议
http header中有个connection属性,close是短链接,connection:keep-alive是长连接,通过这个字段区分长连接和短链接。
优点:
1.减少TCP的握手次数
2.减少慢启动的影响 TCP可以发送很大的资源,100MB以上的这种,但网络带宽是有限的,所以就有一个优化机制,TCP连接都有一个由慢到快的过程,避免一下把带宽占满。
缺点:
tcp也是一种字符流的协议,传输一个文件,要从文件开头传到结尾,一个字节一个字节的传输,顺序不能乱,而且是串行的,会有队头阻塞问题
TCP 之所以可靠,大体上由于以下原因:
数据包校验:目的是检测数据在传输过程中的任何变化,若校验出包有错,则丢弃报文段并且不给出响应,这时 TCP 发送数据端超时后会重发数据;
对失序数据包重排序:既然 TCP 报文段作为 IP 数据报来传输,而 IP 数据报的到达可能会失序,因此 TCP 报文段的到达也可能会失序。TCP 将对失序数据进行重新排序,然后才交给应用层;
丢弃重复数据:对于重复数据,能够丢弃重复数据;
应答机制:当 TCP 收到发自 TCP 连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒;
超时重发:当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段;
流量控制:TCP 连接的每一方都有固定大小的缓冲空间。TCP 的接收端只允许另一端发送接收端缓冲区所能接纳的数据,这可以防止较快主机致使较慢主机的缓冲区溢出,这就是流量控制。
TCP : 可靠(重发机制),传递任意长度消息(字符流协议) 分包通过序列号组合, 阻塞控制 ,需要建立连接,每一条TCP连接只能是1对1,提供全双工通信
UDP: 无连接,不可靠,面向报文,没有阻塞控制,一对一,一对多,多对一,多对多通讯,简单,快速,无队头阻塞的问题
单工数据传输只支持数据在一个方向上传输(电视)
半双工数据传输允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;(对讲机)
全双工数据通信允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。(手机微信)
DNS优化。由于DNS劫持或故障造成的服务不可用,进而影响用户体验。大部分标准DNS都是基于UDP与DNS服务器交互的,HTTPDNS则是利用HTTP协议与DNS服务器交互,绕开了运营商的Local DNS服务,有效防止了域名劫持,提高域名解析效率。简单来说就是DNS解析不通过运营商,通过自己的服务器
升级协议http2.0,多路复用。
数据压缩优化。 传输数据大小的问题。数据对请求速度的影响分两方面,一是压缩率,二是解压序列化反序列化的速度。目前最流行的两种数据格式是 json 和 protobuf,json 是字符串,protobuf 是二进制,即使用各种压缩算法压缩后,protobuf 仍会比 json 小,数据量上 protobuf 有优势,序列化速度 protobuf 也有一些优势
PWA做离线缓存
代理客户。需要主动设置代理服务器IP或者域名进行访问,由正向代理服务器去获取访问内容并返回。相当于中间人借钱,有钱人(服务器)只知道中间人(正向代理服务器)是谁,不知道真正借钱的人(客户端)是谁。隐藏真实的客户,为客户端收发请求,使真实客户端对服务器不可见。
实例:
一个局域网内的所有用户可能被一台服务器做了正向代理,由该台服务器负责 HTTP 请求,意味着同服务器做通信的是正向代理服务器;
代理服务器。不需要客户端做任何设置,反向代理服务器会根据访问内容进行跳转及内容返回,你不知道它最终访问的是哪些机器。隐藏了真实的服务器,为服务器收发请求,使真实服务器对客户端不可见。相当于120电话,打120后不知道哪家医院的救护车会来。
负载均衡服务器,将用户的请求分发到空闲的服务器上; 意味着用户和负载均衡服务器直接通信,即用户解析服务器域名时得到的是负载均衡服务器的 IP。
都是做为服务器和客户端的中间层
都可以加强内网的安全性,阻止 web 攻击
都可以做缓存机制
默认情况下, TCP 连接会启⽤延迟传送算法 (Nagle 算法), 在数据发送之前缓存他们. 如果短时间有多个数据发送, 会缓冲到⼀起作⼀次发送 (缓冲⼤⼩⻅ socket.bufferSize ), 这样可以减少 IO 消耗提⾼性能.
如果是传输⽂件的话, 那么根本不⽤处理粘包的问题, 来⼀个包拼⼀个包就好了. 但是如果是多条消息, 或者是别的⽤途的数据那么就需要处理粘包.
多路复用 支持传输2进制数据类型 服务器端主动推送 header压缩
当然 HTTP/2 也并非完美,考虑一种情况,如果客户端或服务端在通信时出现数据包丢失,或者任何一方的网络出现中断,那么整个 TCP 连接就会暂停。
HTTP/2 由于采用二进制分帧进行多路复用,通常只使用一个 TCP 连接进行传输,在丢包或网络中断的情况下后面的所有数据都被阻塞。但对于 HTTP/1.1 来说,可以开启多个 TCP 连接,任何一个 TCP 出现问题都不会影响其他 TCP 连接,剩余的 TCP 连接还可以正常传输数据。这种情况下 HTTP/2 的表现就不如 HTTP/1 了。
2018 年 HTTP/3 将底层依赖的 TCP 改成 UDP,从而彻底解决了这个问题。UDP 相对于 TCP 而言最大的特点是传输数据时不需要建立连接,可以同时发送多个数据包,所以传输效率很高,缺点就是没有确认机制来保证对方一定能收到数据。
http1.0会,http1.1支持长链接,connection: keep-alive,维持TCP连接,SSL的开销也可以避免。
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Overview https://www.cnblogs.com/chenqf/p/6386163.html https://juejin.im/post/5c7a9f8c518825640d1dd503#heading-16
http状态码
1XX 临时返回,表示客户端继续其请求,被浏览器HTTP库直接处理掉了,不会让上层应用知道
2XX 请求成功
3XX 表示请求的目标有变化,希望客户端进一步处理
301&302:永久性与临时性跳转。
304:跟客户端缓存没有更新。产生这个状态的前提是:客户端本地已经有缓存的版本,并且在 Request 中告诉了服务端,当服务端通过时间或者 tag,发现没有更新的时候,就会返回一个不含 body 的 304 状态
4xx:客户端请求错误。
403:无权限。
404:表示请求的资源不存在。
5xx:内部服务器错误
GET POST请求的区别
GET 参数通过 url 传递,POST 放在 body 中,POST相对安全
GET 请求在 url 中传递的参数是有长度限制的,而 POST 没有,长度限制来源于浏览器对地址栏输入内容的限制,非GET请求本身的限制
GET 在浏览器回退时是无害的(有缓存,协商缓存),而 POST 会再次提交请求,也就是说,GET 请求会被浏览器主动 cache,而 POST 不会,除非手动设置。
GET 请求只能进行 url(x-www-form-urlencoded)编码,而 POST 支持多种编码方式。
GET 产生一个 TCP 数据包;POST 产生两个 TCP 数据包。对于 GET 方式的请求,浏览器会把 http 的 header 和 data 一并发送出去,服务器响应200(返回数据)。而对于 POST,浏览器先发送 header,服务器响应100 continue,浏览器再发送 data,服务器响应200 ok(返回数据)
POST和PUT请求的区别
PUT是幂等的,连续调用一次或者多次的效果相同(无副作用), 如果两个请求相同,后一个请求会把第一个请求覆盖掉 (PUT更多的用来改资源)
POST是非幂等的方式,后一个请求不会把第一个请求覆盖掉(POST更多的用来增资源)
http通用头部字段
Cache-Control 控制缓存
Connection 设置为Keep-alive用于告诉客户端本次HTTP请求结束之后并不需要关闭TCP连接,这样可以使下次HTTP请求使用相同的TCP通道,节省TCP连接建立的时间。
Upgrade 升级为其他协议
via 代理服务器的相关信息
Transfor-Encoding 报文主体的传输编码格式
Pragma 报文指令
Date 创建报文的日期
HTTP请求头里有那些字段
origin:发起请求的服务器地址
Accept :客户端或者代理能够处理的媒体类型
Accept-Encoding 优先可处理的编码格式
Accept-Language 优先可处理的自然语言
Accept-Charset 优先可以处理的字符集
If-Match 比较实体标记(ETage)
If-None-Match 比较实体标记(ETage)与 If-Match相反
If-Modified-Since 比较资源更新时间(Last-Modified)
Authorization web的认证信息 ✨
Host 请求资源所在服务器 ✨
User-Agent 客户端程序信息 ✨
Referer 请求原始放的url
HTTP响应头里有那些字段
Location:令客户端重定向的URI
Last-Modified:该资源最后被修改的时间
set-cookie:设置cookie
content-length
content-type
date ETag
Expires
keep-alive
TCP为什么要三次握手
先大概说一下流程。
第一次握手,客户端发了个连接请求消息到服务端,服务端收到信息后知道自己与客户端是可以连接成功的,但此时客户端并不知道服务端是否已经接收到了它的请求。
第二次握手,服务端接收到消息后的应答,客户端得到服务端的反馈后,才确定自己与服务端是可以连接上的, 客户端只有确定了自己能与服务端连接上才能开始发数据。所以两次握手肯定是最基本的。
第三次握手,是为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误。如果没有第3次,服务器端是不知道客户端有没有接收到服务器端返回的信息,造成服务器端开销的严重浪费。
再归纳一下 每一步。
seq 序列号
ack 确认号,只有ACK为1时,它才有效, ack = seq+1
标志位
ACK: 确认序号有效
SYN: 发起一个新链接
FIN: 释放一个链接
第一次握手,客户端选择一个随机序列号seq(假设为x),并发送一个SYN数据包(1表示开启新连接,0结束连接),其中可能还包括其他TCP标志和选项,客户端将这个数据包给服务器请求连接。
第二次握手, 服务器用一个带有确认应答ACK(1)和同步序列号SYN(1),ack(x+1),seq(假设为y)的数据段,相应客户端,用来通知客户端,服务端已经收到SYN消息并通过了确认。
第三次握手,客户端笑了,说明,client发送给server,server发送给client都可以,但是server不知道这个整体流程走通了没,所以给ACK(1)seq(x+1),ack(y+1)发送握手期间的最后一个数据包,客户端收到数据后,发送数据段确认收到,服务器收到此数据确认无误,开始传送数据
其实第三次握手的时候,是可以携带数据的。但是,第一次、第二次握手不可以携带数据
为什么要有同步序列号。
TCP协议可以是一个全双工通信的,接收方和发起方都可以发送信息,要有一个序列号,表示那些是同一个请求过程中的。序列号也不能从0开始,会混淆的,相对随机生成的,TCP规范中也不允许连接一直是一个半打开的状态。
TCP的4次挥手
1.首先客户端想要释放连接,向服务器端发送一段TCP报文(连接释放报文),FIN=1,seq=x并停止发送数据
2.服务器端接收到从客户端发出的TCP报文之后,确认了客户端想要释放连接,随后服务器端进入一个半关闭的状态(不能一直持续),并返回一段TCP报文(确认报文) ACK=1,ack=x+1,seq=v
3.服务器端准备好后,再次向客户端发出一段TCP报文 FIN =1,ACK=1, seq=w, ack=x+1 关闭。
4.客户端收到从服务器端发出的TCP报文,确认了服务器端已做好释放连接的准备,再次传输一段报文 ACK=1,ack=w+1,seq=x+1
因为TCP是全双工通信,在关闭连接的时候,既要关闭客户端的连接,也要关掉服务端建立的连接,所以需要四次挥手
为什么建立连接只通信了三次,而断开连接却用了四次?
因为当服务端收到客户端的 FIN 报文后,发送的 ACK 报文只是用来应答的,并不表示服务端也希望立即关闭连接。
当只有服务端把所有的报文都发送完了,才会发送 FIN 报文,告诉客户端可以断开连接了,因此在断开连接时需要四次挥手。
TCP建立连接时之所以只需要"三次握手",是因为在第二次"握手"过程中,服务器端发送给客户端的TCP报文是以SYN与ACK作为标志位的。SYN是请求连接标志,表示服务器端同意建立连接;ACK是确认报文,表示告诉客户端,服务器端收到了它的请求报文。
即SYN建立连接报文与ACK确认接收报文是在同一次"握手"当中传输的,所以"三次握手"不多也不少,正好让双方明确彼此信息互通。
TCP释放连接时之所以需要“四次挥手”,是因为FIN释放连接报文与ACK确认接收报文是分别由第二次和第三次"握手"传输的。为何建立连接时一起传输,释放连接时却要分开传输?
建立连接时,被动方服务器端结束CLOSED阶段进入“握手”阶段并不需要任何准备,可以直接返回SYN和ACK报文,开始建立连接。 释放连接时,被动方服务器,突然收到主动方客户端释放连接的请求时并不能立即释放连接,因为还有必要的数据需要处理,所以服务器先返回ACK确认收到报文,经过CLOSE-WAIT阶段准备好释放连接之后,才能返回FIN释放连接报文。
所以是“三次握手”,“四次挥手”。
DNS缓存查询过程
搜索浏览器自身的DNS缓存==> 操作系统的hosts文件==> 查找本地DNS服务器 ==> 根服务器 ==> 顶级服务器
options请求
用于获取目的资源所支持的通信选项。 响应报文包含一个 Allow 首部字段,该字段的值表明了服务器支持的所有 HTTP 方法
在 CORS 中,可以使用 OPTIONS 方法发起一个预检请求,以检测实际请求是否可以被服务器所接受。预检请求报文中的 Access-Control-Request-Method 首部字段告知服务器实际请求所使用的 HTTP 方法;Access-Control-Request-Headers 首部字段告知服务器实际请求所携带的自定义首部字段。服务器基于从预检请求获得的信息来判断,是否接受接下来的实际请求。
HTTP1.0 HTTP1.1 HTTP2.0 的区别
HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法。HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法
HTTP1.1中新增了很多错误状态响应码
HTTP 1.1支持长连接。
在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。通过设置http的请求头部和应答头部,保证本次数据请求结束之后,下一次请求仍可以重用这一通道,避免重新握手。原理是请求完成后不立即释放连接,而是放入连接池中,若这时有另一个请求要发出,请求的域名和端口是一样的,就直接拿出连接池中的连接进行发送和接收数据,少了建立连接的耗时。但有个问题,就是这个 keep-alive 的连接一次只能发送接收一个请求,在上一个请求处理完成之前,无法接受新的请求。
若同时发起多个请求,就有两种情况:若串行发送请求,可以一直复用一个连接,但速度很慢,每个请求都要等待上个请求完成再进行发送。
若并行发送这些请求,那么首次每个请求都要进行tcp三次握手建立新的连接,虽然第二次可以复用连接池里这堆连接,但若连接池里保持的连接过多,对服务端资源产生较大浪费,若限制了保持的连接数,并行请求里超出的连接仍每次要建连。
对这个问题,新一代协议 HTTP2 提出了多路复用去解决。
HTTP/2 采用二进制格式传输数据,解析更高效
多路复用,支持 TCP 连接复用
加密。
HTTPS 有两个作用,一是确定请求的目标服务端身份,二是保证传输的数据不会被网络中间节点窃听或者篡改。HTTPS 是使用加密通道来传输 HTTP 的内容。但是 HTTPS 首先与服务端建立一条 TLS 加密通道。TLS 构建于 TCP 协议之上,它实际上是对传输的内容做一次加密,所以从传输内容上看,HTTPS 跟 HTTP 没有任何区别。
HTTP2.0 支持服务端推送
服务端推送能够在客户端发送第一个请求到服务端时,提前把一部分内容推送给客户端,放入缓存当中,这可以避免客户端请求顺序带来的并行度不高,从而导致的性能问题。 服务端推送能把客户端所需要的资源伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度。例如我的网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了。
TCP 连接复用,则使用同一个 TCP 连接来传输多个 HTTP 请求,避免了 TCP 连接建立时的三次握手开销,和初建 TCP 连接时传输窗口小的问题。
http1.1 中的长链接复用和HTTP2.0中的多路复用的区别
在HTTP/1.1协议中,浏览器客户端在同一时间,针对同一域名下的请求有一定数量限制,超过限制数目的请求会被阻塞。(6个)所谓请求阻塞意思就是一条TCP的connection在同一时间只能允许一个请求经过,这样假如后续请求想要复用这个链接就必须等到前一个完成才行
HTTP/2多个请求可同时在一个连接上并行执行。某个请求任务耗时严重,不会影响到其它连接的正常执行,server端可以根据stream的唯一标识来相应对应的请求。HTTP2 的多路复用看起来是完美的解决方案,但还有个问题,就是队头阻塞,这是受限于 TCP 协议,TCP 协议为了保证数据的可靠性,若传输过程中一个 TCP 包丢失,会等待这个包重传后,才会处理后续的包。HTTP2的多路复用让所有请求都在同一条连接进行,中间有一个包丢失,就会阻塞等待重传,所有请求也就被阻塞了。这个问题无法解决,本身http协议就是基于TCP协议
HTTP的长连接有什么特点
http header中有个connection属性,close是短链接,connection:keep-alive是长连接,通过这个字段区分长连接和短链接。
优点:
1.减少TCP的握手次数
2.减少慢启动的影响 TCP可以发送很大的资源,100MB以上的这种,但网络带宽是有限的,所以就有一个优化机制,TCP连接都有一个由慢到快的过程,避免一下把带宽占满。
缺点:
tcp也是一种字符流的协议,传输一个文件,要从文件开头传到结尾,一个字节一个字节的传输,顺序不能乱,而且是串行的,会有队头阻塞问题
TCP比较可靠?
TCP 之所以可靠,大体上由于以下原因:
数据包校验:目的是检测数据在传输过程中的任何变化,若校验出包有错,则丢弃报文段并且不给出响应,这时 TCP 发送数据端超时后会重发数据;
对失序数据包重排序:既然 TCP 报文段作为 IP 数据报来传输,而 IP 数据报的到达可能会失序,因此 TCP 报文段的到达也可能会失序。TCP 将对失序数据进行重新排序,然后才交给应用层;
丢弃重复数据:对于重复数据,能够丢弃重复数据;
应答机制:当 TCP 收到发自 TCP 连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒;
超时重发:当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段;
流量控制:TCP 连接的每一方都有固定大小的缓冲空间。TCP 的接收端只允许另一端发送接收端缓冲区所能接纳的数据,这可以防止较快主机致使较慢主机的缓冲区溢出,这就是流量控制。
TCP和UDP协议的区别
TCP : 可靠(重发机制),传递任意长度消息(字符流协议) 分包通过序列号组合, 阻塞控制 ,需要建立连接,每一条TCP连接只能是1对1,提供全双工通信
UDP: 无连接,不可靠,面向报文,没有阻塞控制,一对一,一对多,多对一,多对多通讯,简单,快速,无队头阻塞的问题
全双工通信
单工数据传输只支持数据在一个方向上传输(电视)
半双工数据传输允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;(对讲机)
全双工数据通信允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。(手机微信)
弱网环境下的前端优化手段有哪些
DNS优化。由于DNS劫持或故障造成的服务不可用,进而影响用户体验。大部分标准DNS都是基于UDP与DNS服务器交互的,HTTPDNS则是利用HTTP协议与DNS服务器交互,绕开了运营商的Local DNS服务,有效防止了域名劫持,提高域名解析效率。简单来说就是DNS解析不通过运营商,通过自己的服务器
升级协议http2.0,多路复用。
数据压缩优化。 传输数据大小的问题。数据对请求速度的影响分两方面,一是压缩率,二是解压序列化反序列化的速度。目前最流行的两种数据格式是 json 和 protobuf,json 是字符串,protobuf 是二进制,即使用各种压缩算法压缩后,protobuf 仍会比 json 小,数据量上 protobuf 有优势,序列化速度 protobuf 也有一些优势
PWA做离线缓存
正向代理
代理客户。需要主动设置代理服务器IP或者域名进行访问,由正向代理服务器去获取访问内容并返回。相当于中间人借钱,有钱人(服务器)只知道中间人(正向代理服务器)是谁,不知道真正借钱的人(客户端)是谁。隐藏真实的客户,为客户端收发请求,使真实客户端对服务器不可见。
实例:
一个局域网内的所有用户可能被一台服务器做了正向代理,由该台服务器负责 HTTP 请求,意味着同服务器做通信的是正向代理服务器;
反向代理
代理服务器。不需要客户端做任何设置,反向代理服务器会根据访问内容进行跳转及内容返回,你不知道它最终访问的是哪些机器。隐藏了真实的服务器,为服务器收发请求,使真实服务器对客户端不可见。相当于120电话,打120后不知道哪家医院的救护车会来。
实例:
负载均衡服务器,将用户的请求分发到空闲的服务器上; 意味着用户和负载均衡服务器直接通信,即用户解析服务器域名时得到的是负载均衡服务器的 IP。
正向代理和反向代理的共同点
都是做为服务器和客户端的中间层
都可以加强内网的安全性,阻止 web 攻击
都可以做缓存机制
TCP的粘包问题
默认情况下, TCP 连接会启⽤延迟传送算法 (Nagle 算法), 在数据发送之前缓存他们. 如果短时间有多个数据发送, 会缓冲到⼀起作⼀次发送 (缓冲⼤⼩⻅ socket.bufferSize ), 这样可以减少 IO 消耗提⾼性能.
如果是传输⽂件的话, 那么根本不⽤处理粘包的问题, 来⼀个包拼⼀个包就好了. 但是如果是多条消息, 或者是别的⽤途的数据那么就需要处理粘包.
HTTP2.0
多路复用
支持传输2进制数据类型
服务器端主动推送
header压缩
HTTP3.0
当然 HTTP/2 也并非完美,考虑一种情况,如果客户端或服务端在通信时出现数据包丢失,或者任何一方的网络出现中断,那么整个 TCP 连接就会暂停。
HTTP/2 由于采用二进制分帧进行多路复用,通常只使用一个 TCP 连接进行传输,在丢包或网络中断的情况下后面的所有数据都被阻塞。但对于 HTTP/1.1 来说,可以开启多个 TCP 连接,任何一个 TCP 出现问题都不会影响其他 TCP 连接,剩余的 TCP 连接还可以正常传输数据。这种情况下 HTTP/2 的表现就不如 HTTP/1 了。
2018 年 HTTP/3 将底层依赖的 TCP 改成 UDP,从而彻底解决了这个问题。UDP 相对于 TCP 而言最大的特点是传输数据时不需要建立连接,可以同时发送多个数据包,所以传输效率很高,缺点就是没有确认机制来保证对方一定能收到数据。
建立一个TCP连接后,是否会在一个HTTP请求完成断开?
http1.0会,http1.1支持长链接,connection: keep-alive,维持TCP连接,SSL的开销也可以避免。
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Overview
https://www.cnblogs.com/chenqf/p/6386163.html https://juejin.im/post/5c7a9f8c518825640d1dd503#heading-16