看了老是忘系列
Http
概念
超文本传输协议 HyperText Transfer Protocol
状态码
· 1xx
1xx 类状态码属于提示信息,是协议处理中的⼀种中间状态,实际⽤到的⽐较少。
· 2xx
2xx 类状态码表示服务器成功处理了客户端的请求,也是我们最愿意看到的状态。
· 3xx
3xx 类状态码表示客户端请求的资源发送了变动,需要客户端⽤新的URL新发送请求获取资源,也就是重定向。
· 4xx
4xx 类状态码表示客户端发送的报⽂有误,服务器⽆法处理,也就是错误码的含义。
· 5xx
5xx 类状态码表示客户端请求报⽂正确,但是服务器处理时内部发⽣了错误,属于服务器端的错误码
结构
请求报文
1 | POST /xxx/xxx/ HTTP/1.1 |
POST 为请求方法, /xxx/xxx/ 为请求路径, HTTP/1.1 为http版本
Content-Type、Content-Length、Host、Accept-Encoding、User-Agent、Connection 均为请求头 Head中的内容
请求头换行内容为Request Body内容
返回报文
1 | HTTP/1.1 200 OK |
HTTP/1.1 为http版本,200 请求结果状态码, OK 请求结果描述
剩下的为返回报文的 头部信息
请求头换行内容为Result Body内容
Http请求方式
Get
⽤于获取资源、对服务器数据不进⾏修改、不发送 Body、GET把参数包含在URL
1 | GET /xxx/xxx?aaa=111 HTTP/1.1 |
Post
⽤于增加或修改资源发送给服务器的内容写在 Body ⾥⾯
1 | POST /xxx/xxx/ HTTP/1.1 |
Put
和POST 用法一致
Delete
⽤于删除资源,不发送 Body
1 | DELETE /xxx/xxx?id=111 HTTP/1.1 |
HEAD 和 GET 使⽤⽅法完全相同, 和 GET 唯⼀区别在于,返回的响应中没有 Body
当然还有PATCH 这种。平常用到get,post 比较多。 其他的用在RESTful API 中比较多
Post和Get区别
- GET在浏览器回退时是无害的,而POST会再次提交请求。
- GET产生的URL地址可以被Bookmark,而POST不可以。
- GET请求会被浏览器主动cache,而POST不会,除非手动设置。
- GET请求只能进行url编码,而POST支持多种编码方式。
- GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
- GET请求在URL中传送的参数是有长度限制的,而POST么有。
- 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
- GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
- GET参数通过URL传递,POST放在Request body中。
- GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
GET产生一个TCP数据包;POST产生两个TCP数据包。
HTTP是基于TCP/IP的
HTTP是基于TCP/IP的,所以HTTP的请求就是TCP/IP的连接过程。
TCP是什么?
- TCP 提供一种面向连接的、可靠的字节流服务
- 在一个 TCP 连接中,仅有两方进行彼此通信。广播和多播不能用于 TCP
- TCP 给数据分节进行排序,并使用累积确认保证数据的顺序不变和非重复
- TCP 使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制
TCP 为什么可靠
TCP 可靠不是保证数据一定会被对方接收到,因为这是不可能的。TCP 能够做到的是,如果有可能,就把数据递送到接收方,否则就(通过放弃重传并且中断连接这一手段)通知用户。因此准确说 TCP 也不是 100% 可靠的协议,它所能提供的是数据的可靠递送或故障的可靠通知。
TCP链接需要经过三次握手,断开连接需要经过四次挥手
TCP 三次握手
所谓三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个包。
三次握手的目的是连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换 TCP 窗口大小信息。在 socket 编程中,客户端执行 connect() 时。将触发三次握手
第一次握手(SYN=1, seq=x):
客户端发送一个 TCP 的 SYN 标志位置1的包,指明客户端打算连接的服务器的端口,以及初始序号 X,保存在包头的序列号(Sequence Number)字段里。
发送完毕后,客户端进入 SYN_SEND 状态。
(啊喂,胖胖 是我 你在嘛?)
第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1):
服务器发回确认包(ACK)应答。即 SYN 标志位和 ACK 标志位均为1。服务器端选择自己 ISN 序列号,放到 Seq 域里,同时将确认序号(Acknowledgement Number)设置为客户的 ISN 加1,即X+1。 发送完毕后,服务器端进入 SYN_RCVD 状态。
(诶 我是胖胖 我在的)
第三次握手(ACK=1,ACKnum=y+1)
客户端再次发送确认包(ACK),SYN 标志位为0,ACK 标志位为1,并且把服务器发来 ACK 的序号字段+1,放在确定字段中发送给对方,并且在数据段放写ISN的+1
发送完毕后,客户端进入 ESTABLISHED 状态,当服务器端接收到这个包时,也进入 ESTABLISHED 状态,TCP 握手结束。
(噢,胖胖 待会快递到)
TCP 四次挥手
TCP 的连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake),也叫做改进的三次握手。客户端或服务器均可主动发起挥手动作,在 socket 编程中,任何一方执行 close() 操作即可产生挥手操作
第一次挥手(FIN=1,seq=x)
假设客户端想要关闭连接,客户端发送一个 FIN 标志位置为1的包,表示自己已经没有数据可以发送了,但是仍然可以接受数据。
发送完毕后,客户端进入 FIN_WAIT_1 状态。
(我:胖胖, 我想睡觉了, 等胖胖批复中。。。 = FIN_WAIT_1)
第二次挥手(ACK=1,ACKnum=x+1)
服务器端确认客户端的 FIN 包,发送一个确认包,表明自己接受到了客户端关闭连接的请求,但还没有准备好关闭连接。
发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包之后,进入 FIN_WAIT_2 状态,等待服务器端关闭连接。
(胖胖:噢知道了,李佳琦呆会就要上商家我们要买的餐巾纸了 下单就完就睡。。。 胖胖看直播抓紧下单=CLOSE_WAIT 我等她下完单 = FIN_WAIT_2)
第三次挥手(FIN=1,seq=y)
服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN 置为1。
发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个ACK。
(胖胖:好勒 我买好了,睡觉把,你呢 = LAST_ACK)
第四次挥手(ACK=1,ACKnum=y+1)
客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT状态,等待可能出现的要求重传的 ACK 包。
服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。
客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。
(我:好勒 睡觉 = CLOSED)
Http 版本
HTTP有这么几个重要的版本 HTTP1.0 HTTP1.1 HTTP2.0
主要用到的还是HTTP1.1
http1.0
无状态:服务器不跟踪不记录请求过的状态
无连接:浏览器每次请求都需要建立tcp连接
无状态
对于无状态的特性可以借助cookie/session机制来做身份认证和状态记录
无连接
无连接导致的性能缺陷有两种:
无法复用连接
每次发送请求,都需要进行一次tcp连接(即3次握手4次挥手),使得网络的利用率非常低队头阻塞
http1.0规定在前一个请求响应到达之后下一个请求才能发送,如果前一个阻塞,后面的请求也给阻塞的
http1.1
为了解决http1.0的性能缺陷,http1.1出现了
http1.1特性:
长连接:新增Connection字段,可以设置keep-alive值保持连接不断开
管道化:基于上面长连接的基础,管道化可以不等第一个请求响应继续发送后面的请求,但响应的顺序还是按照请求的顺序返回
缓存处理:新增字段cache-control
断点传输
长连接
http1.1默认保持长连接,数据传输完成保持tcp连接不断开,继续用这个通道传输数据
管道化
基于长连接的基础,我们先看没有管道化请求响应:
tcp没有断开,用的同一个通道
请求1 > 响应1 –> 请求2 > 响应2 –> 请求3 > 响应3
管道化的请求响应:
请求1 –> 请求2 –> 请求3 > 响应1 –> 响应2 –> 响应3
即使服务器先准备好响应2,也是按照请求顺序先返回响应1
虽然管道化,可以一次发送多个请求,但是响应仍是顺序返回,仍然无法解决队头阻塞的问题
缓存处理
当浏览器请求资源时,先看是否有缓存的资源,如果有缓存,直接取,不会再发请求,如果没有缓存,则发送请求
通过设置字段cache-control来控制
断点传输
在上传/下载资源时,如果资源过大,将其分割为多个部分,分别上传/下载,如果遇到网络故障,可以从已经上传/下载好的地方继续请求,不用从头开始,提高效率
在 Header 里两个参数实现的,客户端发请求时对应的是 Range 服务器端响应时对应的是 Content-Range
host域
HTTP1.0 不支持,因为之前觉得一台服务器只有一个地址 HTTP2.0 支持,请求消息和响应消息都支持
http2.0
二进制分帧
多路复用: 在共享TCP链接的基础上同时发送请求和响应
头部压缩
服务器推送:服务器可以额外的向客户端推送资源,而无需客户端明确的请求
二进制分帧
将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码
多路复用
基于二进制分帧,在同一域名下所有访问都是从同一个tcp连接中走,http消息被分解为独立的帧,乱序发送,服务端根据标识符和首部将消息重新组装起来
区别
http1.0 到http1.1的主要区别,就是从无连接到长连接
http2.0对比1.X版本主要区别就是多路复用