HTTP 协议
1 网络协议简述
1.1 OSI 七层模型
七层模型,亦称OSI(Open System Interconnection)。参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型。
包括物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
1.2 TCP/IP 协议簇 (四层模型)
TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP 协议不仅仅指的是 TCP 和 IP 两个协议,而是指一个由 FTP、SMTP、TCP、UDP、IP等协议构成的协议簇, 只是因为在TCP/IP协议中 TCP 协议和IP协议最具代表性,所以被称为 TCP/IP 协议。
OSI 是标准模型,TCP/IP 是事实上的模型。
TCP/IP 包括网络接口层、网络层(网际层)、传输层、应用层。
1.3 IP 和 域名
IP 地址
IP 地址是IP 协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个地址。在一个网络中,每台主机的 IP 地址都是唯一的。
类型 | 说明 |
---|---|
本机回环 IP 地址 | 127.0.0.1 ~ 127.255.255.254 |
局域网 IP(私网 IP) | 192.168.0.0 ~ 192.168.255.255 172.16.0.0 ~ 172.31.255.255 10.0.0.0 ~ 10.255.255.255 |
广域网 IP(公网 IP) | 除上述之外 |
windows 想要查看 IP 地址,可以在 CMD 命令行工具中输入命令 ipconfig
linuxs 或 MacOS 想要查看 IP 地址,可以在终端中输入命令 ifconfig
域名
域名是对 IP 的一种映射。
DNS 是进行域名和与之相对应的 IP 地址转换的服务器,DNS中保存了一张域名和与之相对应的IP地址的表,以解析消息的域名。
可以通过阿里云、腾讯云、GoDaddy 等知名服务商购买。
1.4 端口号
所谓的端口,就好像是门牌号一样,客户端可以通过ip地址找到对应的服务器端,但是服务器端是有很多端口的,每个应用程序对应一个端口号,通过类似门牌号的端口号,客户端才能真正的访问到该服务器上的某个应用程序。
0-1023 是公认端口号,即已经公认定义或为将要公认定义的软件保留的,而 1024-65535 是并没有公认定义的端口号,用户可以自己定义这些端口的作用。
常见公认的端口号:
21端口:FTP 文件传输服务
22端口:SSH 端口
23端口:TELNET 终端仿真服务
25端口:SMTP 简单邮件传输服务
53端口:DNS 域名解析服务
80端口:HTTP 超文本传输服务
110端口:POP3 “邮局协议版本3”使用的端口
443端口:HTTPS 加密的超文本传输服务
知名软件的默认端口号:
1433端口:SQLServer数据库 默认端口号
1521端口:Oracle数据库服务
3306端口:MYSQL 默认端口号
3389端口:Microsoft RDP 微软远程桌面使用的端口
5631端口:Symantec pcAnywhere 远程控制数据传输时使用的端口
5632端口:Symantec pcAnywhere 主控端扫描被控端时使用的端口
27017端口:MongoDB 数据库
2 HTTP 协议介绍
HTTP(hypertext transport protocol)协议也叫超文本传输协议,是一种基于 TCP/IP 的应用层通信协议,这个协议详细规定了浏览器和万维网服务器之间互相通信的规则。
协议主要规定了两方面的内容:
客户端向服务器发送数据,称之为请求报文。
服务器向客户端返回数据,称之为响应报文。
2.1 使用工具抓取报文
2.1.1 Fidder 抓包工具
Fiddler 是一个http协议调试代理工具,使用它我们可以抓取网页的所有请求与响应,也就是咱们俗称的抓包。
Fiddler 的安装注意事项:
- 尽量不更换安装位置。
- 安装完毕之后, 桌面默认没有快捷方式,可以点击开始按钮 -> 输入 fiddler -> 点击图标启动程序。
- 配置 Tools -> options -> HTTPS -> 勾选左侧的两个选项 -> 在弹出的对话框中选择 yes 安装证书。
- 关闭电脑的代理工具 ,如 shadowsocks、 v2ry、蓝灯、谷歌访问助手等。
如果关闭 Fiddler 不能上网,可通过下面方法解决:
- 点击开始 -> 代理 -> 取消使用代理服务器。
- 借助 360 卫士之类的工具 -> 工具箱 -> 网络修复。
2.1.2 chrome 浏览器调试工具中的 network 面板
查看看请求行与请求头
查看请求体
查看响应行与响应头
查看响应体
2.2 请求报文
HTTP 请求报文包括四部分:
请求行,用来说明请求类型,要访问的资源以及所使用的 HTTP 版本。
请求头,也称 HTTP 首部,用来说明服务器要使用的附加信息。
空行,请求头部后面的空行是必须的。
请求体,也就请求主体或请求数据,内容格式非常灵活。
2.2.1 请求行
请求行有三部分组成:请求方法、URL、协议版本
请求方法
根据 HTTP 标准,HTTP 请求可以使用多种请求方法。
HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD方法。
HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。
序号 | 方法 | 描述 |
---|---|---|
1 | GET | 请求指定的页面信息,并返回实体主体。 |
2 | HEAD | 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头 |
3 | POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。 |
4 | PUT | 从客户端向服务器传送的数据取代指定的文档的内容。 |
5 | DELETE | 请求服务器删除指定的页面。 |
6 | CONNECT | HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。 |
7 | OPTIONS | 允许客户端查看服务器的性能。 |
8 | TRACE | 回显服务器收到的请求,主要用于测试或诊断。 |
9 | PATCH | 是对 PUT 方法的补充,用来对已知资源进行局部更新 。 |
GET 和 POST 是最常见的两种请求方式,两者具有如下区别:
- GET 主要用来获取数据, POST 主要用来提交数据。通过浏览器访问网页用的就是 GET 请求。
- GET 带参数请求是将参数放到 URL 之后, POST 带参数请求是将参数放到请求体中。
- POST 请求相对 GET 安全一些, 因为GET请求在浏览器中参数会暴露在地址栏。
- GET 请求大小有限制, 一般为
2k,
而 POST 请求则没有大小限制。
URL
统一资源定位系统(uniform resource locator;URL)是因特网的万维网服务程序上用于指定信息位置的表示方法。
http://www.baidu.com:8080/home/msg/data/personalcontent?num=8&indextype=manht#logo
完整 URL 的组成部分:
- 协议 ,如 https、http。
- 主机名,一般使用 IP 地址或域名。
- 端口号 ,HTTP 的端口号为 80,HTTPS 的为 443
- 路径,上面 URL 中的路径部分为:
/home/msg/data/personalcontent
。 - 查询字符串,上面 URL 中的路径部分为:
num=8&indextype=manht
。 - 锚点,上面 URL 中的路径部分为:
#logo
协议版本号
版本号 | 发布时间 |
---|---|
http/1.0 | 1996年 |
http/1.1 | 1999年 |
http/2 | 2015年 |
http/3 | 2018年 |
2.2.2 请求头
请求头格式,请求头键名:值
。
请求头有 HTTP 协议规定的,也有自定义的。HTTP 协议规定的请求头可以查看附录。
2.3 响应报文
HTTP 响应报文也包括四个部分
响应行,也叫状态行,请求报文的起始行说明了要做什么,响应报文的起始行说明发生了什么。
响应头,与请求头类似,也叫 HTTP 首部,也是键值对的形式,表示像客户端说明的附加信息。
空行,响应头部后面的空行是必须的。
响应体,服务器给客户端的数据内容。
2.3.1 响应行
响应行由三部分组成:
- 协议版本。
- 响应状态码,用数字表示响应状态。
- 响应状态描述,用字符串表示响应状态。
2.3.2 响应状态码
状态码由三位数字组成,第一位数字表示响应的类型,常用的状态码有五大类如下所示:
1xx
:指示信息--表示请求已接收,继续处理。2xx
:成功--表示请求已被成功接收、理解、接受。3xx
:重定向--要完成请求必须进行更进一步的操作。4xx
:客户端错误--请求有语法错误或请求无法实现。5xx
:服务器端错误--服务器未能实现合法的请求。
常见状态代码、状态描述的说明如下。
- 200 OK:客户端请求成功。
- 400 Bad Request:客户端请求有语法错误,不能被服务器所理解。
- 401 Unauthorized:请求未经授权
- 403 Forbidden:服务器收到请求,但是拒绝提供服务。
- 404 Not Found:请求资源不存在,举个例子:输入了错误的URL。
- 500 Internal Server Error:服务器发生不可预期的错误。
- 503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常
更多的状态码请查看附录。
2.3.3 响应头
响应头格式,响应头键名:值
。
响应头有 HTTP 协议规定的,也有自定义的。HTTP 协议规定的响应头可以查看附录。
2.3.4 Content-type
在响应头中,有一个 Content-Type
,该响应头告诉客户端实际返回的内容的内容类型,它的值使用 MIME 类型进行标识。
MIME (Multipurpose Internet Mail Extensions),译为多用途互联网邮件扩展类类型也叫媒体类型,是一种标准,用来表示文档、文件或字节流的性质和格式。常见的 MIME 类型如下:
MIME类型 | 含义 |
---|---|
application/octet-stream | 应用程序文件 |
text/plain | 文本文件 |
text/css | css文件 |
text/html | html文件 |
application/javascript | js文件 |
image/gif | GIF 图片 |
image/jpeg | JPEG/JPG 图片 |
image/png | PNG 图片 |
image/svg+xml | SVG图片 (矢量图) |
image/x-icon | icon 图片 |
application/json | json文件 |
multipart/form-data | 上传文件 |
application/x-www-form-urlencoded | Form表单格式 |
audio/webm | WebM 音频文件格式 |
video/webm | WebM 视频文件格式 |
2.4 从域名到网站的过程
注意:访问一个网页的时候,除了请求网页本身之外,还会向服务器请求网页需要的js文件、css文件、图片等
# 1- 通过DNS(domain name system)进行解析找到IP
# 2- 通过IP可以找到服务器
# 3- 每一个服务都有自己独立的端口号,通过端口号找到服务。该服务即是站点服务
# 4- 通过资源地址,找到资源
# 5- 将资源进行响应
# 6- 浏览器得到响应以后,会将响应信息进行渲染,从而可以查看网页。
3 HTTP 数据压缩
3.1 HTTP 数据压缩介绍
1)HTTP压缩是指在 Web 服务器和浏览器间传输压缩文本内容的方法。
2)通过开启服务器端的HTTP压缩功能,也可以提高网站的浏览速度,对优化Ext库文件的传输也不失为一种好的方法。只是该方法会提高服务器 CPU 的负荷。如果服务器CPU本身负荷就大,就需要好好地斟酌了。
3)HTTP压缩的原理是服务器接收到客户端的HTTP请求后,检查浏览器是否支持HTTP压缩,如果支持,则根据配置压缩相应的网页文件,压缩文件下载到客户端后,由浏览器解压文件后再浏览。
4)HTTP压缩的比较通用的算法是 GZIP,所以开启服务端的HTTP压缩功能一般是指开启服务器端的GZIP功能。
3.2 HTTP 数据压缩实现流程
1)请求报文中的请求头 Accept-Encoding,会告知服务器客户端支持的压缩方式。
2)响应报文中的响应头 Content-Encoding,会告知客户端响应数据所使用的压缩方式。
3.3 常用压缩方式及 Node 中的实现
3.3.1 gzip
gzip 的实现算法是在 deflate 格式上增加了文件头和文件尾,
gzip 是最常用的压缩算法,比较推荐。
const zlib = require('zli');
zlib.gzip(data, (err, d) => {
});
3.3.2 defalte
deflate是同时使用了LZ77算法与哈夫曼编码的一个无损数据压缩算法,deflate压缩与解压的源代码可以在自由,通用的压缩库zlib上找到算法实现。
const zlib = require('zli');
zlib.deflate(data, (err, d) => {
});
3.3.4 br
br 全称 brotliCompress,适合压缩较大的文件。
const zlib = require('zli');
zlib.brotliCompress(data, (err, d) => {
});
4 HTTP 缓存机制
4.1 缓存介绍
4.1.1 什么是缓存
缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。当 web 缓存发现请求的资源已经被存储,它会拦截请求,返回该资源的拷贝,而不会去源服务器重新下载。
注意: 一次 http 请求响应所经历的每个网络节点都要相应的缓存机制,我们这里主要研究浏览器缓存。
4.1.2 缓存的好处
1)减少冗余的数据传输,节省带宽费用。
2)缓解网络瓶颈问题,不需要更多的带宽就能更快的加载页面。
3)降低对服务器的要求,服务器可以更快地响应,避免过载的出现。
4)缓存降低了距离时延,因为从较远的地方加载页面会更慢。
4.1.3 相关专业术语
缓存命中:符合条件,就从缓存中加载数据,而不用从服务器下载,称之为命中。
缓存命中率:从缓存中得到数据的请求数与所有请求数的比率。理想状态是越高越好。
- 过期内容:超过设置的有效时间,被标记为“陈旧”的内容。通常过期内容不能用于回复客户端的请求,必须重新向源服务器请求新的内容或者验证缓存的内容是否仍然准备。
- 验证:验证缓存中的过期内容是否仍然有效,验证通过的话刷新过期时间。
- 失效:失效就是把内容从缓存中移除。当内容发生改变时就必须移除失效的内容。
4.1.4 浏览器缓存分类
浏览器缓存分为强制缓存和协商缓存,浏览器加载一个页面的简单流程如下:
- 浏览器先根据这个资源的http头信息来判断是否命中强缓存。如果命中则直接加在缓存中的资源,并不会将请求发送到服务器。
- 如果未命中强缓存,则浏览器会将资源加载请求发送到服务器。服务器来判断浏览器本地缓存是否失效。若可以使用,则服务器并不会返回资源信息,浏览器继续从缓存加载资源。
- 如果未命中协商缓存,则服务器会将完整的资源返回给浏览器,浏览器加载新资源,并更新缓存。
4.2 强制缓存
4.2.1 概念
强制缓存就是在浏览器缓存该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程,简单来讲就是强制浏览器使用当前缓存。
命中强缓存时,浏览器并不会将请求发送给服务器。返回响应状态码是 200,但是会标注 (from cache)。
4.2.2 实现强制缓存
强缓存是利用 http 的响应头中的 Expires 或者 Cache-control 两个字段来控制的,用来表示资源的缓存时间。
注意: Cache-control 优先级比 Expires 高
Expires
缓存过期时间,用来指定资源到期的时间。
该响应头的值是一个时间,比如 Expires:Thu,31 Dec 2037 23:59:59 GMT
。这个时间代表着这个资源的失效时间,也就是说在2037年12月31日23点59分59秒之前都是有效的,即命中缓存。这种方式有一个明显的缺点,由于失效时间是一个绝对时间,所以当客户端本地时间被修改以后,服务器与客户端时间偏差变大以后,就会导致缓存混乱,于是发展出了Cache-Control。
Cache-Control
Cache-Control 可以设置一个相对时间,例如 Cache-Control:max-age=3600
,代表着资源的有效期是 3600 秒,由于是相对时间,并且都是与客户端时间比较,所以服务器与客户端时间偏差也不会导致问题。
Cache-control 可以由多个字段组合而成,主要有以下几个取值:
- max-age 指定一个时间长度,在这个时间段内缓存是有效的,单位是s。例如设置
Cache-Control:max-age=31536000
,也就是说缓存有效期为(31536000 / 24 / 60 * 60)天。 s-maxage 同 max-age,覆盖 max-age、Expires,但仅适用于共享缓存,在私有缓存中被忽略。
no-cache 使用协商缓存。
- no-store 不使用任何缓存。
- public 表明响应可以被任何对象(发送请求的客户端、代理服务器等等)缓存。
- private 默认值,表明响应只能被单个用户(可能是操作系统用户、浏览器用户)缓存,是非共享的,不能被代理服务器缓存。
设置 Cache-Control 的时候,这几个值可以组合在一起使用:
Cache-Control: public, max-age=0, s-maxage=300
Pragma
Pragma 是 HTTP/1.0 标准中定义的一个响应头属性,定义 Pragma: no-cache
的效果跟在头信息中定义 Cache-Control: no-cache
相同,但是 HTTP 的响应头没有明确定义这个属性,所以它不能拿来完全替代 HTTP/1.1 中定义的 Cache-control头。通常定义Pragma以向后兼容基于 HTTP/1.0 的客户端。
4.3 协商缓存
4.3.1 概念
如果未命中强制缓存,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。
命中协商缓存,响应状态码会返回 304。
4.3.2 实现协商缓存
需要设置响应头和请求头来实现协商缓存
服务器端给客户端返回,设置响应头:
- Last-Modified 记录服务器返回资源的最后修改时间。
- Etag 当前文件的唯一标识(由服务器生成)。
客户端给服务器端请求,设置请求头:
- If-Modified-Since 记录服务器返回资源的最后修改时间
- If-None-Match 当前文件的唯一标识(由服务器生成)
注意:Etag / If-None-Match 优先级比 Last-Modified / If-Modified-Since 高。
Last-Modified
Last-Modified 是 HTTP/1.0 规定响应头,标识该资源的最后修改时间,例如 Last-Modify: Thu,31 Dec 2037 23:59:59 GMT
。
Etag
Etag 是 HTTP/1.1 规定的响应头,表示当前文件的唯一标志。
根据 RFC 7232规范,ETag 生成靠以下一种或几种因子,使用抗碰撞散列函数来生成:
- 文件的 i-node 编号,i-node 是 Linux/Unix 用来识别文件的编号。使用命令
ls -l
’可以看到。 - 文件最后修改时间。
- 文件大小。
生成Etag的时候,可以使用其中
HTTP/1.1 为何添加 Etag 这个响应头?以下仅仅使用 Last-Modified 进行验证是不够的:
- 有些文档可能会被被周期性的重写,但实际包含的内容是一样的,尽管内容没有变化,但修改日期会发生变化。
- 有些文档可能被修改了,但所在的修改并不重要(比如拼接或注释的修改),不需要让世界范围内的缓存都重装数据。
- 有些服务器无法准确地判断其页面的最后修改日期。
- Last-Modified 标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间。
4.3.3 协商缓存工作流程
- 第一次请求,服务器返回 Etag 和 Last-Modified 响应头,浏览器收到响应之后,缓存备用。
- 第二次请求浏览器请求时,携带了 If-None-Match(值为上一次的 Etag 的值)和 If-Modified-Since(值为上一次的 Last-Modified 的值)请求头发送给服务器。
- 如果只有请求头 If-None-Match,检查If-None-Match 是否等于最新 Etag 的值,如果相等,命中协商缓存,不等的话,返回新的资源。
- 如果只有请求头 If-Modified-Since ,检查 If-None-Since 是否等于最新的 Last-Modified 的值,如果相等命中协商缓存,不相等就返回新的资源。
- 如果 If-None-Match 和 If-Modified-Since 两个请求头都存在,要求两个都能够匹配,才会命中协商缓存,否则返回新的资源。
4.4 强制缓存和协商缓存整体流程
4.5 缓存返回值
- 200(from memory cache) 命中强制缓存,缓存来自于内存。
- 200(from disk cache),命中强制缓存,缓存来自于磁盘。
- 304 Not Modified,命中协商缓存。
- 200 ,没有命中缓存。
4.6 操作对缓存的影响
浏览器操作 | 强制缓存 | 协商缓存 |
---|---|---|
地址栏回车 | √ | √ |
页面链接跳转(a 链接) | √ | √ |
新开窗口(window.open) | √ | √ |
前进、后退 | √ | √ |
刷新(ctrl + r 和 F5) | X | √ |
强制刷新(ctrl + F5) | X | X |