你好,我是猿java。
提起 HTTP 协议,在互联网时代,它无处不在,不论是网购、看电影、看新闻,还是刷短视频、听音乐、玩游戏,HTTP 都在默默的工作着,尽管 HTTP 如此重要,但还是被很多技术人员给忽略,甚至很多工作多年的老鸟对其中的某些概念也是似是而非,因此今天就来个 HTTP 360度无死角"扫盲"。
发展历史 {#发展历史}
HTTP 诞生 {#HTTP-诞生}
HTTP协议始于 1989 年 Tim Berners-Lee(蒂姆·伯纳斯-李)创建一个以超文本系统为基础的项目,确立了 URI、HTML 三项关键技术,设计并构建了第一个网页浏览器;
HTTP/0.9 {#HTTP-0-9}
20 世纪 90 年代初期,互联网世界非常简陋,存储容量小,网速很慢,计算机处理能力低,尽管 HTTP是个简单的文本协议,但充分验证了 Web 服务的可行性,HTTP/0.9 主要的变更点:
- 传输的数据不再仅限于文本;
- 增加了 HEAD、POST 等新方法;
- 增加了响应状态码,标记可能的错误原因;
- 引入了协议版本号概念;
- 引入了 HTTP Header 的概念,让 HTTP 处理请求和响应更加灵活;
HTTP/1.0 {#HTTP-1-0}
HTTP/1.0 版本在 1996 年正式发布,确立了大部分现在使用的技术,遗憾的是 HTTP/1.0 并不是正式标准,HTTP/1.0 主要功能点变更:
- 传输的数据不再仅限于文本;
- 增加了 HEAD、POST 等方法;
- 增加了响应状态码,标记可能的错误原因;
- 引入了协议版本号概念;
- 引入了 HTTP Header 的概念,让 HTTP 处理请求和响应更加灵活;
HTTP/1.1 {#HTTP-1-1}
1995 年,网景的 Netscape Navigator 和微软的 Internet Explorer 开始了著名的"浏览器大战",于是在"浏览器大战"结束之后的 1999 年,HTTP/1.1 正式发布了 RFC 文档, HTTP/1.1 也成为了一个"正式标准",开启了它长达十余年的传奇生涯(Google、新浪、搜狐、网易、腾讯、Facebook、Twitter、淘宝、京东等知名网站都是在这段时间创立),它是目前互联网上使用最广泛的协议,功能也非常完善,HTTP/1.1 主要的变更点有:
- 增加了 PUT、DELETE 等新的方法;
- 明确了连接管理,允许长连接;
- 允许响应数据分块(chunked),利于传输大文件;
- 增加了缓存管理和控制;
- 强制要求 Host 头,让互联网主机托管成为可能;
HTTP/2 {#HTTP-2}
由于 HTTP/1.1连接慢,无法跟上迅猛发展的互联网,Google 开发了自己的浏览器 Chrome 并推出了新的 SPDY 协议,最终,基于 SPDY 的 HTTP/2 协议在 2015 年发布。HTTP/2 主要的特点有:
- 注重性能改善,考虑了现今互联网的现状:宽带、移动、不安全;
- 采用二进制协议,不再是纯文本;
- 可发起多个请求,废弃了 HTTP/1.1 里的管道;
- 使用专用算法压缩头部,减少数据传输量;
- 允许服务器主动向客户端推送数据;
- 增强了安全性,"事实上"要求加密通信;
HTTP/3 {#HTTP-3}
Google 在开发 HTTP/2的同时 又发明了一个新的协议:QUIC,最后更名成 HTTP/3,开启了 第三代 HTTP 标准。HTTP/3 建立在用户数据报协议 (UDP) 之上。在网络浏览器方面,Chrome v87、Firefox v88 和 Edge v87 都默认启用了 HTTP/3。
HTTP 是什么? {#HTTP-是什么?}
HTTP:HyperText Transfer Protocol,字面意思"超文本传输协议"。如何理解呢? 在这里可以把"超文本传输协议"拆解成 "超文本"、"传输"和"协议" 3部分来讲解。
超文本 {#超文本}
文本:最开始只是简单的字符文字,但发展到现在,"文本"的涵义已经被大大地扩展了,图片、音频、视频、甚至是压缩包,在 HTTP 眼里都可以算做是"文本"。这些文本是完整的、有意义的数据,可以被浏览器、服务器这样的上层应用程序处理。
超文本:就是超越了普通文本的文本,它是文字、图片、音频、视频和压缩包等的混合体,比如:HTML,一个 HTML内部可以有很多定义图片、音频、视频等链接的标签。
传输 {#传输}
传输:在实际生活中,传输就是将物品从 A点 转移到 B点,在网络世界,可以理解成把信息或者数据从 A点移动到B点,因此,HTTP 是一个在计算机世界里专门用来在两点之间传输数据的约定和规范。
协议 {#协议}
协议: 协商共议,因此需要多个角色参与,相互讨论,既然需要讨论,就代表该协议是双向的,而HTTP 是一个用在计算机世界里的协议,它是计算机之间交流通信的规范,以及相关的各种控制和错误处理方式。
最后,对HTTP做一个总结:HTTP 是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范,其特征如下:
- HTTP 是一个用在计算机世界里的协议,它确立了计算机之间交流通信的规范,以及相关的各种控制和错误处理方式;
- HTTP 专门用来在两点之间传输数据,不能用于广播、寻址或路由。
- HTTP 传输的是文字、图片、音频、视频等超文本数据。
- HTTP 是构建互联网的重要基础技术,它没有实体,依赖许多其他的技术来实现,但同时许多技术也都依赖于它。
HTTP 请求方法 {#HTTP-请求方法}
对于接触过REST API开发的小伙伴来说,HTTP的请求方法并不陌生,到目前为止, HTTP/1.1 定义了八种请求方法,方法介绍如下(方法必须是大写形式):
1.GET {#1-GET}
GET方式是指从服务器获取资源,服务器会返回请求的实体数据,自HTTP/0.9 版出现并一直被保留至今,因为是从服务器获取资源,不会对服务器的资源产生修改操作,所以该方法是安全的。另外,多次执行相同的GET操作,结果也都是相同的,因此该方法是幂等。
如下:向 www.yuanjava.cn 发送 GET 请求:
2.HEAD {#2-HEAD}
HEAD方法是指从服务器获取资源,但服务器不会返回请求的实体数据,只会传回响应头,也就是资源的"元信息",HEAD 方法可以看做是 GET 方法的一个"简化版"或者"轻量版"。和 GET方法一样,HEAD也是安全且幂等的。
比如,想要检查一个文件是否存在,只要发个 HEAD 请求就可以了,没有必要用 GET 把整个文件都取下来。如下:向 www.yuanjava.cn 发送 HEAD 请求:
3.POST {#3-POST}
POST 也是一个经常用到的请求方法,用于客户端向服务器传送数据,因为每次 POST操作,服务器的数据都可能会修改,所以该方法不是安全的,另外多次执行同给一个 POST 请求,结果可能也不相同,因此该方法不是幂等的,如下:向 www.yuanjava.cn 发送 POST 请求:
4.PUT {#4-PUT}
类似 POST;在Rest 风格API中,一般使用该方法对应服务器的修改操作,和 POST 方法一样,PUT也是非安全且非幂等的。如下:向 www.yuanjava.cn 发送 PUT 请求:
5.DELETE {#5-DELETE}
DELETE 方法,用于指示服务器删除对应的资源,在Rest 风格API中,一般使用该方法对应服务器的删除操作。
6.CONNECT {#6-CONNECT}
CONNECT 是一个比较特殊的方法,要求服务器为客户端和另一台远程服务器建立一条特殊的连接隧道,这时 Web 服务器在中间充当了代理的角色。实际开发中很难用到。
7.OPTIONS {#7-OPTIONS}
OPTIONS 方法要求服务器列出可对资源实行的操作方法,在响应头的 Allow 字段里返回。它的功能很有限,用处也不大,有的服务器(例如 Nginx)干脆就没有实现对它的支持。
8.TRACE {#8-TRACE}
TRACE 方法多用于对 HTTP 链路的测试或诊断,可以显示出请求 - 响应的传输路径。它的本意是好的,但存在漏洞,会泄漏网站的信息,所以 Web 服务器通常也是禁止使用。
八种方法总结 {#八种方法总结}
- GET:向服务器获取资源,可以理解为读取或者下载数据,该方法是安全且幂等的;
- HEAD:向服务器获取资源的元信息,该方法是安全且幂等的;
- POST:向资源提交数据,相当于写入或上传数据,非安全且非幂等;
- PUT:类似 POST,非安全非幂等;
- DELETE:删除资源,非安全非幂等;
- CONNECT:建立特殊的连接隧道;
- OPTIONS:列出可对资源实行的方法;
- TRACE:追踪请求 - 响应的传输路径。
HTTP 特点 {#HTTP-特点}
应用层协议 {#应用层协议}
HTTP是一种应用层协议,直接面向用户,从上文的分析中已经可以清晰的看到。
无状态 {#无状态}
状态很好理解,比如人的心情,开心,难过,有状态就能很明显的看出人的心情变化。在网络中 "状态"其实就是客户端或者服务器里保存的一些数据或者标志,记录了通信过程中的一些变化信息。
为了更好的说明HTTP的无状态,我们可以先看看 TCP协议的有状态,连接成功后是 ESTABLISHED 状态,断开连接后是 FIN-WAIT 状态,最后又是 CLOSED 状态,而 HTTP,建立连接前两者互不知情,每次收发的报文也都是互相独立的,没有任何的联系。收发报文也不会对客户端或服务器产生任何影响,连接后也不会要求保存任何信息。
因为 HTTP 是无状态的,所以就不需要额外的资源来记录状态信息,这样交互就会相对简单一些
可靠传输 {#可靠传输}
HTTP是基于TCP/IP 协议,因为TCP/IP是可靠传输,所以 HTTP也是可靠传输。
灵活扩展 {#灵活扩展}
HTTP 的灵活扩展可以表现为报文里的各个组成部分都没有做严格的语法语义限制,可以由开发者任意定制,报文内容可以使用空格分隔单词,用换行分隔字段等等
请求-响应 {#请求-响应}
客户端发请求,客户端给出响应,这是 HTTP很寻常的一个交互过程,该过程也证明了HTTP是一个双向协议。
明文 {#明文}
HTTP 协议里面的报文是明文传输,因此用户很容易阅读报文的内容,所以在一定的基础上,明文就意味着不安全,所以 HTTPS可以解决这方面的问题。
HTTP 状态码 {#HTTP-状态码}
在很多抗日神剧中都会出现对暗语的场景,可以根据暗语很快辨别对方身份的真伪,在 HTTP协议中,使用状态码来标识服务器对客户端本次请求的一个响应结果。 在RFC 标准里规定的状态码是三位数,理论上取值范围就是从 000 到 999,RFC 标准把状态码分成了五类,用数字的第一位表示分类,具体如下:
1xx {#1xx}
1××类状态码,属于提示信息,是协议处理的中间状态,实际能够用到的时候很少。常见的 1xx状态码如下图:
2xx {#2xx}
2××类状态码,表示服务器收到并成功处理了客户端的请求。常见的 2xx状态码如下图:
3xx {#3xx}
3xx类状态码,表示客户端请求的资源发生了变动,客户端必须用新的 URI 重新发送请求获取资源,即"重定向"。 常见的 3xx状态码如下图:
4xx {#4xx}
4××类状态码,表示客户端发送的请求报文有误,服务器无法处理,它就是真正的"错误码"含义了。常见的 4xx状态码如下图:
5xx {#5xx}
5××类状态码,表示客户端请求报文正确,但服务器在处理时内部发生了错误,无法返回应有的响应数据,是服务器端的"错误码"。常见的 5xx状态码如下图:
总结 {#总结}
- 1xx:提示信息,表示目前是协议处理的中间状态,还需要后续的操作,实际能够用到的时候很少;
- 2xx:成功,报文已经收到并被正确处理;
- 3xx:重定向,资源位置发生变动,需要客户端重新发送请求;
- 4xx:客户端错误,请求报文有误,服务器无法处理;
- 5xx:服务器错误,服务器在处理请求时内部发生了错误。
HTTP 报文长啥样? {#HTTP-报文长啥样?}
HTTP 协议的请求报文和响应报文的结构基本相同,由三大部分组成:
- 起始行(start line):描述请求或响应的基本信息;
- 头部字段集合(header):使用 key-value 形式更详细地说明报文;
- 消息正文(entity):实际传输的数据,它不一定是纯文本,可以是图片、视频等二进制数据;
起始行和头部字段经常又合称为"请求头"或"响应头",消息正文又称为"实体",但与"header"对应,很多时候就直接称为"body"。
所以,一个完整的 HTTP 报文就像是下图的这个样子,注意在 header 和 body 之间有一个"空行"。
接着看一个HTTP的请求的 wireshark 抓包结果:
报文说明:
|-----------|--------------------------------------------------------------------------------------------|
| 1
| 第一行"GET / HTTP/1.1"就是请求行,而后面的"Host""Connection"等等都属于 header,报文的最后是一个空白行结束,没有 body。
|