HTTP入门到放弃
1.网络基础
TCP/IP协议族按层次:
- 应用层 http协议 DNS..
- 传输层 TCP传输控制协议 UDP用户数据报协议...
- 网络层 IP协议...
- 链路层
chrome一次性只能处理6个tcp请求。其他的请求必须等待6个请求完成,这个等待时间是构成stalling的主要部分
与http协议关系密切的协议: IP,TCP,DNS
- 负责传输的IP协议: 把各种数据包传递给对方,两个最重要的条件是IP地址和MAC地址 ARP解析地址的协议
- 确保可靠性的TCP协议: 采用三次握手的策略 利用两个TCP标志,SYN(synchronize)和ACK(acknowledgement)
- 负责域名解析的DNS服务: 提供域名到IP地址之间的解析服务
TCP
sequenceDiagram
发送端->>接收端: 标有SYN的数据包发送给你了
接收端->>发送端:收到!并发送标有SYN/ACK的数据包
发送端->接收端: 明白!发送标有ACK的数据包
三者在http协议通讯过程中发挥的作用
发送端从上往下走,接收端从下往上走
客户端:访问www.baidu.com/xss/web.html
经过DNS协议:返回对应的IP地址
HTTP协议的职责:生成对应的http请求报文 (请给我www.baidu.com/xss/web.html 页面的资源)
TCP协议的职责:将HTTP请求报文分割成报文段把每个报文段(打上标记序号和端口号)可靠地传给对方
IP协议:搜索对方的地址,一遍中转一遍传送
--发送端在层与层之间传递数据时,每经过一层就会打上该层的首部信息,
--反之,接受端在层与层之间传递数据时,每经过一层就会把对应的首部消去
服务器端:
TCP协议的职责:从对方那里接受报文段,按序号以原来的顺序重组
HTTP协议的职责:对Web服务器请求内容的处理 (原来是想要这台计算机上xss/资源呀)
请求的结果也同样利用TCP/IP通讯协议向用户回传
2.简单的HTTP协议
- HTTP协议用于客户端和服务端之间的通讯
- 通过请求和响应的交换达成通讯
- 请求报文是由请求方法,请求URI,协议版本号,可选的请求头部字段和内容实体构成
- 响应报文是由协议版本,状态码,用以解释状态码的原因短语,可选的响应首部字段,以及实体
- HTTP不保存状态的协议 无状态(stateless)协议
- 告知服务器意图的HTTP请求
GET 获取资源
GET方法用来请求访问已被URI识别的资源。指定的资源京服务器解析后返回响应的内容
POST 传输实体主体 post主要目的并不是获取响应的主体内容,而是 ‘我要把信息告诉你’
PUT 传输文件
HEAD 获取报文首部
DELETE 删除文件
OPTIONS 询问支持的方法 ‘你支持什么方法?’
TRACE 追踪路径
CONNECT 要求用隧道协议连接代理
持久连接 Connection:keep-alive
持久连接的特点:只要任意一端没有明确提出断开连接,就保持TCP连接状态,减少了TCP连接建立和断开造成的额外开销,减轻服务器负担
管道化
同时并行发送多个请求
cookie技术
Cookie技术通过在请求和响应报文中加入Cookie信息来控制服务端状态
Cookie会根据从服务器端发送的响应报文中的Set-Cookie的首部字段信息,通知客服端保存Cookie,当下次服务端再往该服务器发送请求时会自动在请求报文中加入cookie字段
服务器端发现客户端发送过来的cookie回去检查是哪个客户端发来的请求,然后对比服务器上的记录,最后得到之前的状态
第一次没有cookie信息下的请求:
客户端发送请求,服务端生成Cookie记住是谁发送的,然后偶在响应首部信息中加Set-Cookie返回,客户端保存Cookie
第二次之后(存有cookie)的请求
客户端请求 在首部信息中自动添加cookie 服务端检查cookie,再响应
3.http报文中的http信息
本章了解请求和响应是如何运作的
用于HTTP协议交互的信息被成为HTTP报文,分为报文首部,报文主体
- 请求报文
- 报文首部
- 请求行 (请求的方法,请求URI HTTP版本)
- 请求首部字段
- 通用首部字段
- 实体首部字段
- 空行(CR+LF)
- 报文主体
- 报文首部
- 响应报文
- 报文首部
- 状态行 (状态码,原因短语 HTTP版本)
- 响应首部字段
- 通用首部字段
- 实体首部字段
- 空行(CR+LF)
- 报文主体
- 报文首部
首部字段中包含请求响应的各种条件和属性的各类首部
编码提成传输速率
- 压缩传输的内容编码,分类:
- gzip (GUN zip)
- compress (UNIX系统的标准压缩)
- deflate (zlib)
- identity (不压缩)
- 分块发送的分块传输编码 --把实体主体分块
发送多种数据的多部分对象集合
通常在文件上传是使用
- multipart/form-data 文件上传时使用
- multipart/buteranges 响应206(部分内容)包含了多个范围的内容时使用
- content-Type: multipart/form-data ;boundary=xxxx 使用boundary花纹多部分对象集合指明的各类实体
获取部分内容的范围请求
- 从5001到10000字节Range: bytes=5001-10000,xxxx-xxxx
- 从5001到最后字节Range: bytes=5001-
- 针对范围请求,会响应206 另外对于多重范围的范围请求,会在响应首部加上mutipart/buyeranges
- 若服务器无法响应范围请求,则返回200以及完整实体内容
内容协商返回最合适的内容
内容协商机制是指客户端和服务端就响应的资源内容进行交涉,然后提供给客户端最合适的资源。 一般包括 语言,字符集,编码方式为基准判断响应的资源
- Accept
- Accept-Charset
- Accept- Encoding
- Accept-Language
- Content-Language
内容协商技术分为三类:
- 服务器驱动协商
- 客户端驱动协商
- 透明协商
4.常见HTTP状态码
本章介绍HTTP状态码
状态码的职责是当客户端向服务端发送请求时,描述返回的请求。
header 1 | 类别 | 原因短语 |
---|---|---|
1XX | Informational(信息性状态码) | 接受的请求正在处理 |
2XX | Success(成功状态码) | 请求正确处理完毕 |
3XX | Redirection(重定向) | 需要进行附加操作以完成请求 |
4XX | Client Error(客户端错误状态码) | 服务器无法处理请求 |
5XX | Server Error(服务端错误状态码) | 服务端处理请求出错 |
2xx 成功
2xx的响应结果表明请求被正确处理了
- 200 OK
客户端发来的请求被正确处理了 - 204 No Content
请求被正确处理了,但是没有资源可返回。(一般只需要从客户端往服务器发送信息,二队客户端不需要发送新信息内容的情况下使用。) - 206 Partial Content (对资源某一部分的请求)
表明客户端进行了范围请求,而服务器成功执行了这部分的GET请求,请求不成功则会返回200请求全部
3xx 重定向
3xx响应结果表明服务器需要执行某些特殊的处理以正确处理请求
301 Moved Permanently (资源的URI已更新,你也更新下你的书签引用吧)
永久性重定向。 请求的资源已被分配了新的URL,以后应使用现在的URI。如果保存了书签,这时应该按Location首部字段提示的URI保存。302 Found (资源的URI已临时定位到其他位置,姑且算你已经知道这个情况了)
临时性重定向。 请求的资源已被分配了新的URL,希望用户(本次)能使用新的URI访问 不会更新书签303 See Other (资源的URI已更新,你是否能临时按新的URI访问呢)
请求对象的资源存在着另外一个URI,应使用GET请求定向获取请求的资源304 Not Modified (资源已找到,但是未符合条件请求 )
表示客户端发送附带条件的请求时,服务器端允许请求访问资源,但因为请求为未满足条件的情况后,直接返回304(服务器端资源未改变,可直接使用客户端未过期的缓存) (并且不返回任何的响应主体部分,虽然304划分在3xx类别中,但是和重定向没有半毛钱关系) 附带条件的请求指的是:GET方法的请求报文中包含 If-Match If-None-Match If-Range If-Unmodified-since中的任一首部字段
307 Temporary Redirect
临时重定向。与302有相同的含义,尽管302禁止POST变换为GET,但实际上大家并不遵守。307遵照浏览器标准不会将POST改为GET,但浏览器处理各不相同
4xx客户端错误
4xx的响应结果表明客户端是发生错误的原因所在。
400 Bad Request (我无法理解这个请求,是不是错了?)
请求报文中存在语法错误。浏览器会想200 ok一样对待改状态码401 Unauthorized (本页面需要认证)
发送的请求你需要有通过HTTP认证(BASIC认证,DIGEST认证)的认证信息。若之前请求过一次,则用户认证失败。 返回401的响应必须包含一个适用于被请求资源的WWW-Authenticate首部用以质询(challenge)用户信息。当浏览器初次接收到401时,会弹出认证用的对话框。403 Forbidden (不允许访问那个资源哇) 对请求资源的访问被服务器拒绝了。
未获得文件系统的访问授权,访问权限出现某些问题时(从未授权的发送源IP地址试图访问)出现
404 Not Found (求的资源服务器没有请)
服务器上无法找到请求的资源,或者服务器端拒绝请求并且不想说明理由时用~
5xx服务器错误
5xx的响应结果表明服务器本身发生错误
500 Internal Server Error (内部资源出现故障)
服务器端在执行球球的时候发生错误。当然也可能是Web应用存在的bug或后写临时的故障导致。503 Service Unavailable
服务器暂时处在超负荷或者正在停机维护,现在无法处理请求。如果事先得知解除以上状况需要的时间,最好写入 Retry-After首部字段给客户端。
此外,状态码和状态可能不一致,比如Web应用程序内部发生错误,状态码依然返回200 ok。
UDP
- UDP 相比 TCP 简单的多,不需要建立连接,不需要验证数据报文,不需要流量控制,只会把想发的数据报文一股脑的丢给对端
- 虽然 UDP 并没有 TCP 传输来的准确,但是也能在很多实时性要求高的地方有所作为
TCP
- 建立连接需要三次握手,断开连接需要四次握手
- 滑动窗口解决了数据的丢包、顺序不对和流量控制问题
- 拥塞窗口实现了对流量的控制,保证在全天候环境下最优的传递数据
GET POST
在规范的应用场景上说,Get 多用于无副作用,幂等的场景,例如搜索关键字。Post 多用于副作用,不幂等的场景,例如注册
技术上:
- Get 请求能缓存,Post 不能
- Post 相对 Get 安全一点点,因为Get 请求都包含在 URL 里(当然你想写到 body 里也是可以的),且会被浏览器保存历史纪录。Post 不会,但是在抓包的情况下都是一样的
- URL有长度限制,会影响 Get 请求,但是这个长度限制是浏览器规定的,不是 RFC 规定的
- Post 支持更多的编码类型且不对数据类型限制
TLS
HTTPS 还是通过了 HTTP 来传输信息,但是信息通过 TLS 协议进行了加密。
TLS 中使用了两种加密技术,对称加密和非对称加密
对称加密
- 两边拥有相同的秘钥,两边都知道如何将密文加密解密
- 这种加密方式固然很好,但是问题就在于如何让双方知道秘钥。因为传输数据都是走的网络,如果将秘钥通过网络的方式传递的话,一旦秘钥被截获就没有加密的意义的。
非对称加密
- 有公钥私钥之分,公钥所有人都可以知道,可以将数据用公钥加密,但是将数据解密必须使用私钥解密,私钥只有分发公钥的一方才知道。
- 这种加密方式就可以完美解决对称加密存在的问题。假设现在两端需要使用对称加密,那么在这之前,可以先使用非对称加密交换秘钥。
流程:
首先服务端将公钥公布出去,那么客户端也就知道公钥了。接下来客户端创建一个秘钥,然后通过公钥加密并发送给服务端,服务端接收到密文以后通过私钥解密出正确的秘钥,这时候两端就都知道秘钥是什么了
HTTP2
HTTP/2 很好的解决了当下最常用的 HTTP/1 所存在的一些性能问题,只需要升级到该协议就可以减少很多之前需要做的性能优化工作,当然兼容问题以及如何优雅降级应该是国内还不普遍使用的原因之一。
在 HTTP/1 中,为了性能考虑,我们会引入雪碧图、将小图内联、使用多个域名等等的方式。这一切都是因为浏览器限制了同一个域名下的请求数量(Chrome 下一般是限制六个连接),当页面中需要请求很多资源的时候,队头阻塞(Head of line blocking)会导致在达到最大请求数量时,剩余的资源需要等待其他资源请求完成后才能发起请求。
多路复用
HTTP/2引入了多路复用技术
,可以只通过一个 TCP 连接就可以传输所有的请求数据。多路复用很好的解决了浏览器限制同一个域名下的请求数量的问题,同时也接更容易实现全速传输,毕竟新开一个 TCP 连接都需要慢慢提升传输速度
在 HTTP/2 中,有两个非常重要的概念,分别是帧(frame)和流(stream)。
帧代表着最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流。
多路复用,就是在一个 TCP 连接中可以存在多条流。换句话说,也就是可以发送多个请求,对端可以通过帧中的标识知道属于哪个请求。通过这个技术,可以避免 HTTP 旧版本中的队头阻塞问题,极大的提高传输性能。
二进制传输(所有加强性能的核心点在于此)
http1是以文本的方式传输数据,http2引入了新的编码机制,所有传输的数据都被分割,并采用二进制格式编码
Header 压缩
在 HTTP /2 中,使用了 HPACK 压缩格式对传输的 header 进行编码,减少了 header 的大小。并在两端维护了索引表,用于记录出现过的 header ,后面在传输过程中就可以传输已经记录过的 header 的键名,对端收到数据后就可以通过键名找到对应的值
服务端push
服务端可以在客户端某个请求后,主动推送其他资源
某些资源客户端是一定会请求的,这时就可以采取服务端 push 的技术,提前给客户端推送必要的资源,这样就可以相对减少一点延迟时间。当然在浏览器兼容的情况下你也可以使用 prefetch 。
HTTP3
HTTP2还有一个大问题,是底层支撑的TCP协议的问题。
http2使用多路复用,一般一个域名下只需要一个TCP连接,当这个链接出现丢包
,就会导致HTTP2的表现不如HTTP1.
当出现丢包,真个TCP都要开始等待重传,就导致后面的数据都被阻塞,但是多余HTTP1来说,可以开启多个TCP链接,一个连接不会影响其他。
Google 弄了一个基于 UDP 协议的 QUIC
协议,并且使用在了 HTTP/3 上,当然 HTTP/3 之前名为 HTTP-over-QUIC,从这个名字中我们也可以发现,HTTP/3 最大的改造就是使用了 QUIC,接下来我们就来学习关于这个协议的内容。
QUIC
QUIC 虽然基于 UDP,但是在原本的基础上新增了很多功能,比如多路复用、0-RTT、使用 TLS1.3 加密、流量控制、有序交付、重传等等功能。
多路复用
虽然 HTTP/2 支持了多路复用,但是 TCP 协议终究是没有这个功能的。QUIC 原生就实现了这个功能,并且传输的单个数据流可以保证有序交付且不会影响其他的数据流,这样的技术就解决了之前 TCP 存在的问题
并且 QUIC 在移动端的表现也会比 TCP 好。因为 TCP 是基于 IP 和端口
去识别连接的,这种方式在多变的移动端网络环境下是很脆弱的。但是 QUIC 是通过 ID
的方式去识别一个连接,不管你网络环境如何变化,只要 ID 不变,就能迅速重连上。
0-RTT
通过使用类似 TCP 快速打开的技术,缓存当前会话的上下文,在下次恢复会话的时候,只需要将之前的缓存传递给服务端验证通过就可以进行传输了。
纠错机制
假如说这次我要发送三个包,那么协议会算出这三个包的异或值并单独发出一个校验包,也就是总共发出了四个包。
当出现其中的非校验包丢包的情况时,可以通过另外三个包计算出丢失的数据包的内容。
当然这种技术只能使用在丢失一个包的情况下,如果出现丢失多个包就不能使用纠错机制了,只能使用重传的方式了。
输入 URL 到页面渲染的整个流程
- 首先
DNS
查询,通过域名查找到具体的IP
因为 IP 存在数字和英文的组合(IPv6),很不利于人类记忆,所以就出现了域名。你可以把域名看成是某个 IP 的别名,DNS 就是去查询这个别名的真正名称是什么
接下来是 TCP 握手,应用层会下发数据给传输层,这里 TCP 协议会指明两端的端口号,然后下发给网络层。网络层中的 IP 协议会确定 IP 地址,并且指示了数据传输中如何跳转路由器。然后包会再被封装到数据链路层的数据帧结构中,最后就是物理层面的传输了
当 TCP 握手结束后就会进行 TLS 握手,然后就开始正式的传输数据。
数据在进入服务端之前,可能还会先经过负责
负载均衡的服务器
,它的作用就是将请求合理的分发到多台服务器上,这时假设服务端会响应一个 HTML 文件首先浏览器会判断状态码是什么,如果是 200 那就继续解析,如果 400 或 500 的话就会报错,如果 300 的话会进行重定向,这里会有个重定向计数器,避免过多次的重定向,超过次数也会报错
浏览器开始解析文件,如果是 gzip 格式的话会先解压一下,然后通过文件的编码格式知道该如何去解码文件
文件解码成功后会正式开始渲染流程
先会根据 HTML 构建
DOM 树
,有 CSS 的话会去构建CSSOM 树
。如果遇到 script 标签的话,会判断是否存在async
或者defer
,前者会并行进行下载并执行 JS,后者会先下载文件,然后等待 HTML 解析完成后顺序执行。如果以上都没有,就会阻塞住渲染流程直到 JS 执行完毕。遇到文件下载的会去下载文件,这里如果使用 HTTP/2 协议的话会极大的提高多图的下载效率。CSSOM 树和 DOM 树构建完成后会开始生成
Render 树
,这一步就是确定页面元素的布局、样式等等诸多方面的东西在生成 Render 树的过程中,浏览器就开始调用 GPU 绘制,合成图层,将内容显示在屏幕上了。