一、HTTP协议是什么
每当我们打开浏览器,输入网址,点击链接,浏览网页时,背后都在发生着一场看不见的"数据接力"。这些数据是如何从服务器准确无误地传送到我们电脑上的?中间又经历了怎样的过程?今天,我们就来深入探讨互联网数据传输的基石------HTTP和HTTPS协议。
HTTP(HyperText Transfer Protocol,超文本传输协议)是一种应用非常广泛的应用层协议。是当前 web 开发中最核心的协议,但凡使用网站,都会用到HTTP协议。
那么,协议 是什么意思?为了使数据能够完好无损地从源头发送到目的地,参与网络通信的收发方必须遵循相同的规则,这套规则就是协议,最终体现为网络上传输的数据包的格式。
简单来说,协议就类似一种暗号,只有懂得相同的暗号才能将数据传输过去。

HTTP诞生于1991年,目前已成为最主流的一种网络协议。
简单来说,当我们在浏览器中输入一个网址(URL),浏览器就会给服务器发送一个HTTP请求,服务器接收到请求后计算响应并返回HTTP响应。这个响应被浏览器解析之后,就展示成我们看到的内容了。
HTTP/1.0、HTTP/1.1和HTTP/2.0的底层基于TCP协议实现,而HTTP/3.0则是基于UDP协议实现。
二、HTTP协议的工作过程
当我们访问一个网站,此时浏览器会给对应的服务器发送一个HTTP请求,服务器收到请求后经过计算得到一个HTTP响应,然后返回给浏览器,浏览器接收到响应我们就会看到网站内容了。

其实,当我们访问网站时,涉及到的HTTP请求/响应的交互可能不止一次。
我们当前学习的HTTP协议的特点就是
一问一答,即有几条请求就会返回几条响应。当然还有不同的收发模式:
- 多问一答:如上传一个大文件
- 一问多答:如下载一个大文件
- 多问多答:如远程控制程序
三、HTTP协议格式
HTTP是一个文本格式的协议,我们可以通过两种方法查看协议细节:
- 浏览器自带的开发者工具,如Chrome按下F12可以开启开发者工具,然后点击Network就可以查看具体的通信交互细节了
- 使用抓包工具,我们使用Fiddler(专门抓包HTTP协议)来抓包HTTP协议以查看具体细节
3.1 Fiddler抓包工具
什么是抓包工具?
抓包工具是一个能够获取到网络通信的数据包并且解析详细的格式的软件,电脑上的所有网络通信数据包都会先发给抓包工具,然后由抓包工具转发给服务器。
简单来说,抓包工具相当于一个代理,负责将请求/响应这些通信内容转发给服务器/浏览器,分为:
- 正向代理:代替浏览器转发请求给对应服务器
- 反向代理:代替服务器转发响应给浏览器
但是,未经授权的抓包操作可能涉及到信息安全,因此务必要注意抓包工具的使用!
目前较知名的抓包工具是 wireshark,可以抓包多个协议的数据包(HTTP、TCP、UDP、IP、以太网数据帧...),但是,使用的门槛较高,因此我们暂不使用。
Fiddler 是一个专门抓包HTTP协议的抓包工具,且使用起来简单、方便。
在这个页面下滑,找到 Fiddler Classic,我们要下载的就是这个版本(因为它免费~)

然后点击 "here" 跳转页面,点击 "Try For Free",
跳转到这个页面,输入信息就可以下载了(下载速度较慢的话可能需要魔法~)

下载完成后,点击 tool -> option 选项卡,然后点击 HTTPS
第一次下载可能需要你信任Fiddler的根证书,这里一定要点击 YES!!否则就得卸载重装了~
然后页面就是这样(目前我的浏览器正在请求的是CSDN,因为我正在写文章):

可以看到,左边栏显示抓包到的数据包有很多,其实电脑上随时都会有很多程序在偷偷的运行。
这里的颜色也有不同:
- 红色表示报错,可能是请求失败了
- 蓝色表示请求得到了一个网页
- 绿色表示请求得到了一个JavaScript
- 灰色表示响应的数据已被缓存
右边上栏的就是请求的原始数据(要点击 raw),下栏的是响应的原始数据(原来是压缩了的,我这里是解压之后的了,点击中间的黄色的带有decode的那个条条就可以解压了)。
那为什么响应要压缩传输呢?其实是为了节省网络带宽,因为响应的正文部分比较长,如果直接传送会很吃带宽,而带宽资源又贵的很~
3.2 请求格式结构
我们通过 Fiddler 抓包到请求的原始数据,点击 "View in Notepad" 可以在记事本中打开原始数据


这个就是请求的原始数据,接下来我们来认识一下它的格式结构。
请求结构包含四个部分:
首行:包含了请求方法、URL和版本号请求头(header):是键值对结构空行:请求头的结束标志正文(body):有些请求有正文有些则没有

3.3 响应格式结构
在 Fiddler 的右下栏就是响应的数据,点击中间的黄色长条可以解压,然后点击 "raw" 就可以显示响应的原始数据了



接下来我们来看看响应的结构。
响应的结构包含:
- 首行:包含协议版本、响应状态码和状态码描述。其中的响应状态码表示请求的处理结果:1xx是信息性状态,表示临时响应,与客户端继续操作;2xx是成功状态,表示请求已处理成功;3xx是重定向状态,表示资源已移动,需客户端重定向;4xx是客户端错误状态,表示请求有误(如URL错误);5xx是服务器错误状态,表示服务器处理失败。而状态码描述就是为了方便理解响应(100对应 continue,200对应 OK,302对应 Found,404对应 Not Found,500对应 Internal Server Error)
- 响应头(header):也是键值对结构
- 空行:是响应头的结束标志
- 正文(body):返回浏览器的内容,若是网站则是HTML

3.4 协议格式结构总结

四、HTTP请求详解(Request)
4.1 认识 URL
URL(Uniform Resource Locator统一资源定位符)就是用来描述网络上唯一资源的位置。互联网上的每一个文件都有一个唯一的URL,它包含了文件的位置以及浏览器如何使用等信息。
- 这是一条标准的URL:
http://user:pass@www.example.jp:80/dir/index.htm?uid=1#ch1
- 一个具体的URL(我的CSDN主页):
https://blog.csdn.net/REGARD712?spm=1011.2415.3001.5343
接下来我们来分析:
https是一个协议名称,本质是 http + s(保护层ssl)起到保密作用,这里我们使用https协议访问CSDN网站,若是访问数据库MySQL,则应写成"jdbc:mysql"user:pass是登录信息,可以看到在这里省略了,因为现在网站进行身份认证一般不再通过URL了。blog.csdn.net服务器地址,这里是一个域名,域名可以通过DNS域名解析系统来转换成一个具体的IP地址端口号,这里省略了端口号,当省略端口号,浏览器就会自动根据协议类型决定使用哪个端口号(http协议默认使用80端口,https协议默认使用443端口)带有层次结构的路径,每一层相当于一个目录,目录中还可以有子目录查询字符串(query string),对要访问的资源进行补充说明,也是键值对结构,键值对之间使用 "&" 来分隔,键和值之间使用 "=" 来分隔,程序员可以自己定义这里的内容片段标识符,对于含有不同文档的网站来说,使用不同的片段标识符可以跳转到不同的文档,这里是CSDN主页没有包含文档,因此此处省略了
4.2 认识 URL encode
当我们搜索的时候输入汉字,比如搜索马斯克,看到浏览器上方的URL中的查询字符串中显示着"埃隆·马斯克"中文汉字,

于是复制下来整个 URL,却发现粘贴得到的 URL 的查询字符串中,原本是中文汉字的地方变成了一堆看不懂的字符:

这是怎么一回事?
其实,由于程序员可以自行定义查询字符串,如果定义的符号和原本 URL 指定的带有特殊含义的符号(如. / ? # &等等)冲突了,那就会将该符号转义。转义的规则是:将需要转码的字符由二进制转成十六进制,然后从右到左依次取4位,每2位做一位,在前面加上 "%",最终编码成 "%XY" 的形式。
在这里,中文字符是由 UTF-8 或者 GBK 编码构成的,虽然在 URL 中没有特殊含义,但是仍然需要进行转义,否则浏览器可能把 UTF-8/GBK 编码中的某个字节当做 URL 中的特殊符号。
4.3 认识 "方法" (method)
| 方法 | 说明 | 支持的HTTP协议版本 |
|---|---|---|
GET |
获取资源 | 1.0、1.1 |
POST |
传输实体主体 | 1.0、1.1 |
| PUT | 传输文件 | 1.0、1.1 |
| HEAD | 获得报文首部 | 1.0、1.1 |
| DELETE | 删除文件 | 1.0、1.1 |
| OPTIONS | 询问支持的方法 | 1.1 |
| TRACE | 追踪路径 | 1.1 |
| CONNECT | 要求用隧道协议连接代理 | 1.1 |
| LINK | 建立和资源之间的联系 | 1.0 |
| UNLINE | 断开连接 | 1.0 |
这里有很多的方法,使用最多的方法是 GET 和 POST,因此我们主要讲一下这两个方法。
4.3.1 GET 方法
GET 方法是HTTP协议中最常用的方法,常用于获取服务器上的某个资源。
向浏览器网址栏输入一个 URL,此时浏览器就会发送一个 GET 请求给对应的服务器。
并且,HTML的 link、img 和 script 等标签也可以触发 GET 请求;JavaScript 中的 ajax 也可以构造出 GET 请求。
接下来,我访问一下我的 CSDN 主页并使用 Fiddler 抓包 GET 请求:

GET 请求中的特点:
- 首行的第一个是 GET
- URL 的查询字符串可以为空也可以不为空,这里不为空
- 请求报头header部分有若干个键值对
- 正文body部分为空

- 关于 GET 请求的 URL 的长度问题:
- 网上有些资料上描述,GET 请求长度最多1024KB,这样的说法其实是不正确的,HTTP 协议由 RFC 2616 标准定义, 标准原⽂中明确说明: "Hypertext Transfer Protocol -- HTTP/1.1,"does not specify any requirement for URL length. 也就是说,标准定义中并没有限制 URL 的长度。
- 实际 URL 的长度取决于浏览器的实现和HTTP服务器端的实现。在浏览器端,不同的浏览器最大长度是不同的,但现代浏览器支持的长度一般都很长;在服务器端,长度一般都可以配置的。
4.3.2 POST 方法
POST 方法多用于登录界面,将用户信息提交给服务器,可以通过HTML中的 form 标签构造请求,也可以使用 JavaScript 的 ajax 构造构造请求。
通过 Fiddler 抓包我登录力扣时候的 POST 请求:

POST 请求中的特点:
- 首行的第一个是 POST
- URL 的查询字符串一般为空(也可以不为空)
- 请求包头header部分有若干对键值对
- 正文body部分一般不为空,body 中的数据格式是通过 header 中的
Content-Type来指定,body 的长度由 header 中的Content-Length来指定

面试题:谈谈 GET 和 POST 的区别
- 语义上,
并没有本质的区别,在一些场景可以混着用。GET 也可以用于提交数据,POST 也可以用以获取数据。只是在使用是有点细微差别:GET 习惯将数据放在 查询字符串(query string)中传输,而正文(body)部分则为空;而 POST 则习惯将数据放在正文(body)中传输,而查询字符串(query string)部分是空的。GET 请求一般是幂等的,而 POST 请求一般没有要求幂等。由于 GET 被要求是幂等的,就可以将数据缓存下来,而 POST 一般没要求幂等,一般也不允许将数据缓存。- 补充:幂等是什么意思?
简单来说就是"执行一次和执行多次的结果是一致的",比如双十一、抢票等这类抢购的场景,如果一个用户抢到了,并且进入支付页面,但是此时刚好卡了,用户就又点了两三次支付按钮,等到页面恢复正常,支付的金额并不会因为用户多点了两三次而多扣费,而是和用户点一次支付按钮的结果是一样的。- 关于 POST 比 GET 更安全的误解:
- 误解:网上有些人说,在登录的场景下,GET 比 POST 更加安全。因为若是 GET 请求,登录的时候用户输入的数据就会被放到 query string 中,而 query string 中的键值对是可以通过浏览器的 URL 栏看到的,但若是 POST 请求,数据就会被放到 body 中,在 URL 栏就无法看到了。
- 正解:安全与否取决于是否有加密以及加密的强度,与放在请求中的位置无关。因为 GET 和 POST 请求都可以通过抓包工具获取到,重要的是加密了没有。
- 关于 GET 只能传输文本数据、POST 可以传输二进制的误解
- 误解:网上有人说 GET 只能传输文本数据;POST 既可以传输文本数据,也可以传输二进制数据
- 正解: GET 也可以传输二进制数据,虽然不能直接在 query string 中传输二进制数据,但是可以针对二进制数据通过 URL encode 转码,然后就可以放到 URL 中;GET 还可以直接将二进制数据放到 body 中(少部分情况)。
今天就到这里吧,若有错误请尽管指出~
完


