admin 管理员组文章数量: 887016
透视 HTTP 协议学习
01 | 时势与英雄:HTTP的前世今生
1989 年,任职于欧洲核子研究中心(CERN)的**蒂姆·伯纳斯 - 李(
Tim Berners-Lee
)**发表了一篇论文,提出了在互联网上构建超链接文档系统的构想。这篇论文中他确立了三项关键技术。
- URI:即统一资源标识符,作为互联网上资源的唯一身份;
- HTML:即超文本标记语言,描述超文本文档;
- HTTP:即超文本传输协议,用来传输超文本。
HTTP/0.9
只允许用“GET”动作从服务器上获取 HTML 文档,并且在响应请求之后立即关闭连接,功能非常有限。
HTTP/1.0
- 增加了 HEAD、POST 等新方法;
- 增加了响应状态码,标记可能的错误原因;
- 引入了协议版本号概念;
- 引入了 HTTP Header(头部)的概念,让 HTTP 处理请求和响应更加灵活;
- 传输的数据不再仅限于文本。
但 HTTP/1.0 并不是一个“标准”,只是记录已有实践和模式的一份参考文档,不具有实际的约束力,相当于一个“备忘录”。
HTTP/1.1
HTTP/1.1 是对 HTTP/1.0 的小幅度修正。但一个重要的区别是:它是一个“正式的标准”,而不是一份可有可无的“参考文档”。这意味着今后互联网上所有的浏览器、服务器、网关、代理等等,只要用到 HTTP 协议,就必须严格遵守这个标准,相当于是互联网世界的一个“立法”
- 增加了 PUT、DELETE 等新的方法;
- 增加了缓存管理和控制;
- 明确了连接管理,允许持久连接;
- 允许响应数据分块(chunked),利于传输大文件;
- 强制要求 Host 头,让互联网主机托管成为可能;
HTTP/2
Google 首先开发了自己的浏览器 Chrome,然后推出了新的 SPDY 协议, SPDY 为基础开始制定新版本的 HTTP 协议,最终在 2015 年发布了 HTTP/2
- 二进制协议,不再是纯文本;
- 可发起多个请求,废弃了 1.1 里的管道;
- 使用专用算法压缩头部,减少数据传输量;
- 允许服务器主动向客户端推送数据;
- 增强了安全性,“事实上”要求加密通信。
HTTP/3
在 HTTP/2 还处于草案之时,Google 又发明了一个新的协议,叫做 QUIC,而且还是相同的“套路”,继续在 Chrome 和自家服务器里试验着“玩”,依托它的庞大用户量和数据量,持续地推动 QUIC 协议成为互联网上的“既成事实”。
小结
- HTTP 协议始于三十年前蒂姆·伯纳斯 - 李的一篇论文;
- HTTP/0.9 是个简单的文本协议,只能获取文本资源;
- HTTP/1.0 确立了大部分现在使用的技术,但它不是正式标准;
- HTTP/1.1 是目前互联网上使用最广泛的协议,功能也非常完善;
- HTTP/2 基于 Google 的 SPDY 协议,注重性能改善,但还未普及;
- HTTP/3 基于 Google 的 QUIC 协议,是将来的发展方向。
课下作业
- 你认为推动 HTTP 发展的原动力是什么?
- 你是怎么理解 HTTP(超文本传输协议)的?
- HTTP 的本质是 P(Protocol),即一个协议,定义了服务端与客户端数据交互的标准。
超文本有超链接,是网状结构,文本是线性结构
HTTP2.0
的新特点:“二进制协议,不再是纯文本”。 那像 HTTP/1.1 中的application/octet-stream
和multipart/form-data
也属于本文格式吗?
- 是的,只要是HTTP/1.1,就都是文本格式,虽然里面的数据可能是二进制,但分隔符还是文本,这些都会在“进阶篇”里讲。
ftp、telnet
使用前必须输入用户名和密码,更偏向于一对一的使用,对用户来说不够开放。 而http设计之初就是对所有用户开放,而且还统一了访问方式,使用门槛很低,就会有很多人用。至于后续各种优化和功能的添加,那都是顺其自然的事了。 所以总的来说,是http对用户的开放性,使得用户推动其蓬勃发展
04 | HTTP世界全览(下):与HTTP相关的各种协议
- TCP 协议是“Transmission Control Protocol”的缩写,意思是“传输控制协议”,它位于 IP 协议之上,基于 IP 协议提供可靠的、字节流形式的通信,是 HTTP 协议得以实现的基础。“可靠”是指保证数据不丢失,“字节流”是指保证数据完整,所以在 TCP 协议的两端可以如同操作文件一样访问传输的数据,就像是读写在一个密闭的管道里“流动”的字节。
- IP 协议是“Internet Protocol”的缩写,主要目的是解决寻址和路由问题,以及如何在两点间传送数据包。IP 协议使用“IP 地址”的概念来定位互联网上的每一台计算机。现在我们使用的 IP 协议大多数是 v4 版,地址是四个用“.”分隔的数字,例如“192.168.0.1”,总共有 2^32,大约 42 亿个可以分配的地址。 v6 版,使用 8 组“:”分隔的数字作为地址,容量扩大了很多,有 2^128 个
- DNS在 TCP/IP 协议中使用 IP 地址来标识计算机,但对于人类来说却既难以记忆又难以输入。于是“域名系统”(Domain Name System)出现了,用有意义的名字来作为 IP 地址的等价替代。在 DNS 中,“域名”(Domain Name)又称为“主机名”(Host)。
- URI(Uniform Resource Identifier),中文名称是 统一资源标识符,使用它就能够唯一地标记互联网上资源。
- URL(Uniform Resource Locator), 统一资源定位符,也就是我们俗称的“网址”,它实际上是 URI 的一个子集,不过因为这两者几乎是相同的,差异不大,所以通常不会做严格的区分。
- URI 主要有三个基本的部分构成:
http://nginx/en/download.html
- 协议名:即访问该资源应当使用的协议,在这里是“http”;
- 主机名:即互联网上主机的标记,可以是域名或 IP 地址,在这里是“nginx”;
- 路径:即资源在主机上的位置,使用“/”分隔多级目录,在这里是“/en/download.html”。
- HTTPS:全称是“HTTP over SSL/TLS”,也就是运行在 SSL/TLS 协议上的 HTTP。
- SSL 的全称是“Secure Socket Layer”使用了许多密码学最先进的研究成果,综合了对称加密、非对称加密、摘要算法、数字签名、数字证书等技术,能够在不安全的环境中为通信的双方创建出一个秘密的、安全的传输通道,为 HTTP 套上一副坚固的盔甲
- 这里 SSL/TLS,而不是 TCP/IP,它是一个负责加密通信的安全协议,建立在 TCP/IP 之上,所以也是个可靠的传输协议,可以被用作 HTTP 的下层。
- 浏览器地址栏,如果有一个小锁头标志,那就表明网站启用了安全的 HTTPS 协议,而 URI 里的协议名,也从“http”变成了“https”。
- 代理(Proxy)是 HTTP 协议中请求方和应答方中间的一个环节,作为“中转站”,既可以转发客户端的请求,也可以转发服务器的应答。
- 匿名代理:完全“隐匿”了被代理的机器,外界看到的只是代理服务器;
- 透明代理:顾名思义,它在传输过程中是“透明开放”的,外界既知道代理,也知道客户端;
- 正向代理:靠近客户端,代表客户端向服务器发送请求;
- 反向代理:靠近服务器端,代表服务器响应客户端的请求;
- CDN,实际上就是一种代理,它代替源站服务器响应客户端的请求,通常扮演着透明代理和反向代理的角色。
- 代理在传输过程中插入了一个“中间层”,所以可以在这个环节做很多有意思的事情,比如:
- 负载均衡:把访问请求均匀分散到多台机器,实现访问集群化;
- 内容缓存:暂存上下行的数据,减轻后端的压力;
- 安全防护:隐匿 IP, 使用 WAF 等工具抵御网络攻击,保护被代理的机器;
- 数据处理:提供压缩、加密等额外的功能
小结
- TCP/IP 是网络世界最常用的协议,HTTP 通常运行在 TCP/IP 提供的可靠传输基础上;
- DNS 域名是 IP 地址的等价替代,需要用域名解析实现到 IP 地址的映射;
- URI 是用来标记互联网上资源的一个名字,由“协议名 + 主机名 + 路径”构成,俗称 URL;
- HTTPS 相当于“HTTP+SSL/TLS+TCP/IP”,为 HTTP 套了一个安全的外壳;
- 代理是 HTTP 传输过程中的“中转站”,可以实现缓存加速、负载均衡等功能。
课后作业
- DNS 与 URI 有什么关系?
- 在讲代理时我特意没有举例说明,你能够用引入一个“小强”的角色,通过打电话来比喻一下吗?
1:DNS 与 URI 有什么关系? DNS专门用于域名解析,作用是简化人类记忆数据的复杂度。 URI专门用于标识互联网世界中的资源,作用是帮助找到对应的互联网中资源。 互联网中的电脑通过IP地址来表示,DNS可以把一个域名变成一个IP地址,IP地址是标识资源的一部分,仅定位了具体的电脑,还有继续定位在电脑上的具体位置。
2:在讲代理时我特意没有举例说明,你能够用引入一个“小强”的角色,通过打电话来比喻一下吗? 小强给小明打电话要小红的照片——小明是正向代理 小强要小红的照片小明负责处理——小明是反向代理
网络通信是分布式系统的底座,也是信息交互的法宝
- TCP——负责数据传输
- IP——负责标识传输对象
- DNS——负责简化人类的记忆
- URI/L——负责标识传输的资源
- SSL——负责数据传输的安全
- Proxy——负责信息的中转 像极了走标,
- 需要搞清楚从哪到哪——IP
- 需要搞定怎么传输——TCP
- 需要保障货物的安全——SSL
- 需要送货的具体位置——URI
- 需要把目的地的经纬度换成地址名——DNS
- 需要中间中转一下——Proxy
- HTTP——我不那么多,我向你要什么你就给什么
05|常说的四层 和 七层到底是什么?五层和六层哪去了
四层 TCP/IP 的协议栈
第一层叫“链接层”(link layer),负责在以太网、WiFi 这样的底层网络上发送原始数据包,工作在网卡这个层次,使用 MAC 地址来标记网络上的设备,所以有时候也叫 MAC 层。
第二层叫“网际层”或者“网络互连层”(internet layer),IP 协议就处在这一层。因为 IP 协议定义了“IP 地址”的概念,所以就可以在“链接层”的基础上,用 IP 地址取代 MAC 地址,把许许多多的局域网、广域网连接成一个虚拟的巨大网络,在这个网络里找设备时只要把 IP 地址再“翻译”成 MAC 地址就可以了。
第三层叫“传输层”(transport layer),这个层次协议的职责是保证数据在 IP 地址标记的两点之间“可靠”地传输,是 TCP 协议工作的层次,另外还有它的一个“小伙伴”UDP。TCP 是一个有状态的协议,需要先与对方建立连接然后才能发送数据,而且保证数据不丢失不重复。而 UDP 则比较简单,它无状态,不用事先建立连接就可以任意发送数据,但不保证数据一定会发到对方。两个协议的另一个重要区别在于数据的形式。TCP 的数据是连续的“字节流”,有先后顺序,而 UDP 则是分散的小数据包,是顺序发,乱序收。关于 TCP 和 UDP 可以展开讨论的话题还有很多,比如最经典的“三次握手”和“四次挥手”,一时半会很难说完,好在与 HTTP 的关系不是太大,以后遇到了再详细讲解。
协议栈的第四层叫“应用层”(application layer),由于下面的三层把基础打得非常好,所以在这一层就“百花齐放”了,有各种面向具体应用的协议。例如 Telnet、SSH、FTP、SMTP 等等,当然还有我们的 HTTP。
MAC 层的传输单位是帧(frame),IP 层的传输单位是包(packet),TCP 层的传输单位是段(segment),HTTP 的传输单位则是消息或报文(message)。但这些名词并没有什么本质的区分,可以统称为数据包。
七层协议栈:
第一层:物理层,网络的物理形式,例如电缆、光纤、网卡、集线器等等;
第二层:数据链路层,它基本相当于 TCP/IP 的链接层;
第三层:网络层,相当于 TCP/IP 里的网际层;
第四层:传输层,相当于 TCP/IP 里的传输层;
第五层:会话层,维护网络中的连接状态,即保持会话和同步;
第六层:表示层,把数据转换为合适、可理解的语法和语义(编解码);
第七层:应用层,面向具体的应用传输数据。
四层和七层的对应关系:
但 OSI 模型也是有优点的。对比一下就可以看出,TCP/IP 是一个纯软件的栈,没有网络应有的最根基的电缆、网卡等物理设备的位置。而 OSI 则补足了这个缺失,在理论层面上描述网络更加完整。还有一个重要的形式上的优点:OSI 为每一层标记了明确了编号,最底层是一层,最上层是七层,而 TCP/IP 的层次从来只有名字而没有编号。显然,在交流的时候说“七层”要比“应用层”更简单快捷,特别是英文,对比一下“Layer seven”与“application layer”。
第一层:物理层,TCP/IP 里无对应;
第二层:数据链路层,对应 TCP/IP 的链接层;
第三层:网络层,对应 TCP/IP 的网际层;第四层:传输层,对应 TCP/IP 的传输层;
第五、六、七层:统一对应到 TCP/IP 的应用层。
所以你看,这就是“理想与现实”之间的矛盾。理想很美好,有七层,但现实很残酷,只有四层,“多余”的五层、六层就这样“消失”了。
但这也有一定的实际原因。OSI 的分层模型在四层以上分的太细,而 TCP/IP 实际应用时的会话管理、编码转换、压缩等和具体应用经常联系的很紧密,很难分开。例如,HTTP 协议就同时包含了连接管理和数据格式定义。
所谓的“四层负载均衡”就是指工作在传输层上,基于 TCP/IP 协议的特性,例如 IP 地址、端口号等实现对后端服务器的负载均衡。
所谓的“七层负载均衡”就是指工作在应用层上,看到的是 HTTP 协议,解析 HTTP 报文里的 URI、主机名、资源类型等数据,再用适当的策略转发给后端服务器。
小节
- TCP/IP 分为四层,核心是二层的 IP 和三层的 TCP,HTTP 在第四层;
- OSI 分为七层,基本对应 TCP/IP,TCP 在第四层,HTTP 在第七层;
- OSI 可以映射到 TCP/IP,但这期间一、五、六层消失了;
- 日常交流的时候我们通常使用 OSI 模型,用四层、七层等术语;
- HTTP 利用 TCP/IP 协议栈逐层打包再拆包,实现了数据传输,但下面的细节并不可见。
- 有一个辨别四层和七层比较好的(但不是绝对的)小窍门,“两个凡是”:凡是由操作系统负责处理的就是四层或四层以下,否则,凡是需要由应用程序(也就是你自己写代码)负责处理的就是七层。
课下作业
- 你能用自己的话解释一下“二层转发”“三层路由”吗?
- 你认为上一讲中的 DNS 协议位于哪一层呢?
- 你认为 CDN 工作在那一层呢?
1 二层转发:设备工作在链路层,帧在经过交换机设备时,检查帧的头部信息,拿到目标mac地址,进行本地转发和广播
2 三层路由:设备工作在ip层,报文经过有路由功能的设备时,设备分析报文中的头部信息,拿到ip地址,根据网段范围,进行本地转发或选择下一个网关
3 dns,网络请求的第一步是域名解析,所以工作在应用层
4 cdn,应用层
08 | 键入网址再按下回车,后面究竟发生了什么?
因为我们在地址栏里直接输入了 IP 地址“127.0.0.1”,而 Web 服务器的默认端口是 80,所以浏览器就要依照 TCP 协议的规范,使用“三次握手”建立与 Web 服务器的连接。对应到 Wireshark 里,就是最开始的三个抓包,浏览器使用的端口是 52085,服务器使用的端口是 80,经过 SYN、SYN/ACK、ACK 的三个包之后,浏览器与服务器的 TCP 连接就建立起来了。
有了可靠的 TCP 连接通道后,HTTP 协议就可以开始工作了。于是,浏览器按照 HTTP 协议规定的格式,通过 TCP 发送了一个“GET / HTTP/1.1”请求报文,也就是 Wireshark 里的第四个包。至于包的内容具体是什么现在先不用管,我们下一讲再说。
随后,Web 服务器回复了第五个包,在 TCP 协议层面确认:“刚才的报文我已经收到了”,不过这个 TCP 包 HTTP 协议是看不见的。Web 服务器收到报文后在内部就要处理这个请求。同样也是依据 HTTP 协议的规定,解析报文,看看浏览器发送这个请求想要干什么。它一看,原来是要求获取根目录下的默认文件,好吧,那我就从磁盘上把那个文件全读出来,再拼成符合 HTTP 格式的报文,发回去吧。这就是 Wireshark 里的第六个包“HTTP/1.1 200 OK”,底层走的还是 TCP 协议。
同样的,浏览器也要给服务器回复一个 TCP 的 ACK 确认,“你的响应报文收到了,多谢”,即第七个包。这时浏览器就收到了响应数据,但里面是什么呢?所以也要解析报文。一看,服务器给我的是个 HTML 文件,好,那我就调用排版引擎、JavaScript 引擎等等处理一下,然后在浏览器窗口里展现出了欢迎页面。
这之后还有两个来回,共四个包,重复了相同的步骤。这是浏览器自动请求了作为网站图标的“favicon.ico”文件,与我们输入的网址无关。但因为我们的实验环境没有这个文件,所以服务器在硬盘上找不到,返回了一个“404 Not Found”。
至此,“键入网址再按下回车”的全过程就结束了。
使用 IP 地址访问 Web 服务器
简要叙述一下这次最简单的浏览器 HTTP 请求过程:
- 浏览器从地址栏的输入中获得服务器的 IP 地址和端口号;
- 浏览器用 TCP 的三次握手与服务器建立连接;
- 浏览器向服务器发送拼好的报文;
- 服务器收到报文后处理请求,同样拼好报文再发给浏览器;
- 浏览器解析报文,渲染输出页面。
使用域名访问 Web 服务器
- 浏览器看到了网址里的“www.chrono”,发现它不是数字形式的 IP 地址,那就肯定是域名了,于是就会发起域名解析动作
- 浏览器首先看一下自己的缓存里有没有,如果没有就向操作系统的缓存要,还没有就检查本机域名解析文件 hosts,也就是上一讲中我们修改的
“C:\WINDOWS\system32\drivers\etc\hosts”
小结
- HTTP 协议基于底层的 TCP/IP 协议,所以必须要用 IP 地址建立连接;
- 如果不知道 IP 地址,就要用 DNS 协议去解析得到 IP 地址,否则就会连接失败;
- 建立 TCP 连接后会顺序收发数据,请求方和应答方都必须依据 HTTP 规范构建和解析报文;
- 为了减少响应时间,整个过程中的每一个环节都会有缓存,能够实现“短路”操作;
- 虽然现实中的 HTTP 传输过程非常复杂,但理论上仍然可以简化成实验里的“两点”模型。
课下作业
- 你能试着解释一下在浏览器里点击页面链接后发生了哪些事情吗?
- 1 浏览器缓存 > 2 系统缓存 > 3本地hosts > 4 根域名 > 5 顶级dns服务器(如 com) > 6 二级dns服务器(baidu) > 7 三级dns服务器(
www.baidu
)
- 1 浏览器缓存 > 2 系统缓存 > 3本地hosts > 4 根域名 > 5 顶级dns服务器(如 com) > 6 二级dns服务器(baidu) > 7 三级dns服务器(
- 这一节课里讲的都是正常的请求处理流程,如果是一个不存在的域名,那么浏览器的工作流程会是怎么样的呢?
- 先查浏览器缓存,然后是系统缓存->hosts文件->根域名服务器> 顶级域名服务器>广域网域名服务器>局域网域名服务器,最终找不到以后,返回一个报错页面,chrome是
ERR_CONNECTION_ABORTED
- 先查浏览器缓存,然后是系统缓存->hosts文件->根域名服务器> 顶级域名服务器>广域网域名服务器>局域网域名服务器,最终找不到以后,返回一个报错页面,chrome是
问:DNS域名解析不需要发请求,建立连接吗?本地缓存的dns除外。 比如我第一次访问一个域名abc,那这第一次不是需要从dns服务器上拿真正的IP吗,去拿IP的这个过程不是应该也是一个请求吗?这个请求又是什么请求呢?
答复:dns请求是专门的dns协议,使用udp发送,因为是udp所以不需要建立连接。
09 | HTTP报文是什么样子的?
报文结构
TCP 报文来举例,它在实际要传输的数据之前附加了一个 20 字节的头部数据,存储 TCP 协议必须的额外信息,例如发送方的端口号、接收方的端口号、包序号、标志位等等。有了这个附加的 TCP 头,数据包才能够正确传输,到了目的地后把头部去掉,就可以拿到真正的数据。
HTTP 协议的请求报文和响应报文的结构基本相同,由三大部分组成:
- 起始行(start line):描述请求或响应的基本信息;
- 头部字段集合(header):使用 key-value 形式更详细地说明报文;
- 消息正文(entity):实际传输的数据,它不一定是纯文本,可以是图片、视频等二进制数据。
这其中前两部分起始行和头部字段经常又合称为“请求头”或“响应头”,消息正文又称为“实体”,但与“header”对应,很多时候就直接称为“body”。HTTP 协议规定报文必须有 header,但可以没有 body,而且在 header 之后必须要有一个“空行”,也就是“CRLF”,十六进制的“0D0A”。
在这个浏览器发出的请求报文里,第一行“GET / HTTP/1.1”就是请求行,而后面的“Host”“Connection”等等都属于 header,报文的最后是一个空白行结束,没有 body。虽然 HTTP 协议对 header 的大小没有做限制,但各个 Web 服务器都不允许过大的请求头,因为头部太大可能会占用大量的服务器资源,影响运行效率。
请求行
请求报文里的起始行也就是请求行,它简要地描述了客户端想要如何操作服务器端的资源。请求行由三部分构成:
- 请求方法:是一个动词,如 GET/POST,表示对资源的操作;
- 请求目标:通常是一个 URI,标记了请求方法要操作的资源;
- 版本号:表示报文使用的 HTTP 协议版本。
这三个部分通常使用空格(space)来分隔,最后要用 CRLF 换行表示结束。
GET / HTTP/1.1
状态行
响应报文里的起始行,标识服务器响应的状态。
- 版本号:表示报文使用的 HTTP 协议版本;
- 状态码:一个三位数,用代码的形式表示处理的结果,比如 200 是成功,500 是服务器错误;
- 原因:作为数字状态码补充,是更详细的解释文字,帮助人理解原因。
HTTP/1.1 200 OK
HTTP/1.1 404 Not Found
头部字段
头部字段是 key-value 的形式,key 和 value 之间用“:”分隔,最后用 CRLF 换行表示字段结束。比如在“Host: 127.0.0.1”这一行里 key 就是“Host”,value 就是“127.0.0.1”。
HTTP 头字段非常灵活,不仅可以使用标准里的 Host、Connection 等已有头,也可以任意添加自定义头,这就给 HTTP 协议带来了无限的扩展可能。
不过使用头字段需要注意下面几点:
- 字段名不区分大小写,例如“Host”也可以写成“host”,但首字母大写的可读性更好;
- 字段名里不允许出现空格,可以使用连字符“-”,但不能使用下划线“_”。例如,“test-name”是合法的字段名,而“test name”“test_name”是不正确的字段名;
- 字段名后面必须紧接着“:”,不能有空格,而“:”后的字段值前可以有多个空格;
- 字段的顺序是没有意义的,可以任意排列不影响语义;
- 字段原则上不能重复,除非这个字段本身的语义允许,例如 Set-Cookie。
常用头字段
HTTP 协议规定了非常多的头部字段,实现各种各样的功能,但基本上可以分为四大类:
- 通用字段:在请求头和响应头里都可以出现;
- 请求字段:仅能出现在请求头里,进一步说明请求信息或者额外的附加条件;
- 响应字段:仅能出现在响应头里,补充说明响应报文的信息;
- 实体字段:它实际上属于通用字段,但专门描述 body 的额外信息。
对 HTTP 报文的解析和处理实际上主要就是对头字段的处理,理解了头字段也就理解了 HTTP 报文。
- **Host 字段: 它属于请求字段,只能出现在请求头里,它同时也是唯一一个 HTTP/1.1 规范里要求必须出现的字段,也就是说,如果请求头里没有 Host,那这就是一个错误的报文。**例如我们的试验环境,在 127.0.0.1 上有三个虚拟主机:“www.chrono”“www.metroid”和“origin.io”。那么当使用域名的方式访问时,就必须要用 Host 字段来区分这三个 IP 相同但域名不同的网站,否则服务器就会找不到合适的虚拟主机,无法处理。
- User-Agent : 只出现在请求头里。它使用一个字符串来描述发起 HTTP 请求的客户端,服务器可以依据它来返回最合适此浏览器显示的页面。由于历史的原因,User-Agent 非常混乱,每个浏览器都自称是“Mozilla”“Chrome”“Safari”,企图使用这个字段来互相“伪装”,导致 User-Agent 变得越来越长,最终变得毫无意义。不过有的比较“诚实”的爬虫会在 User-Agent 里用“spider”标明自己是爬虫,所以可以利用这个字段实现简单的反爬虫策略。
- Date 字段: 是一个通用字段,但通常出现在响应头里,表示 HTTP 报文创建的时间,客户端可以使用这个时间再搭配其他字段决定缓存策略。
- Server 字段: 是响应字段,只能出现在响应头里。它告诉客户端当前正在提供 Web 服务的软件名称和版本号,例如在我们的实验环境里它就是“Server: openresty/1.15.8.1”,即使用的是 OpenResty 1.15.8.1。Server 字段也不是必须要出现的,因为这会把服务器的一部分信息暴露给外界,如果这个版本恰好存在 bug,那么黑客就有可能利用 bug 攻陷服务器。所以,有的网站响应头里要么没有这个字段,要么就给出一个完全无关的描述信息。比如 GitHub,它的 Server 字段里就看不出是使用了 Apache 还是 Nginx,只是显示为“GitHub”。
- Content-Length 字段: 表示报文里 body 的长度,也就是请求头或响应头空行后面数据的长度。服务器看到这个字段,就知道了后续有多少数据,可以直接接收。如果没有这个字段,那么 body 就是不定长的,需要使用 chunked 方式分段传输。
小结
- HTTP 报文结构就像是“大头儿子”,由“起始行 + 头部 + 空行 + 实体”组成,简单地说就是“header+body”;
- HTTP 报文可以没有 body,但必须要有 header,而且 header 后也必须要有空行,形象地说就是“大头”必须要带着“脖子”;
- 请求头由“请求行 + 头部字段”构成,响应头由“状态行 + 头部字段”构成;
- 请求行有三部分:请求方法,请求目标和版本号;
- 状态行也有三部分:版本号,状态码和原因字符串;
- 头部字段是 key-value 的形式,用“:”分隔,不区分大小写,顺序任意,除了规定的标准头,也可以任意添加自定义字段,实现功能扩展;
- HTTP/1.1 里唯一要求必须提供的头字段是 Host,它必须出现在请求头里,标记虚拟主机名。
课下作业
- 如果拼 HTTP 报文的时候,在头字段后多加了一个 CRLF,导致出现了一个空行,会发生什么?
- 在header 下面第一个空行以后都会被当作body 体
- 讲头字段时说“:”后的空格可以有多个,那为什么绝大多数情况下都只使用一个空格呢?
- 头部多一个空格就会多一个传输的字节,去掉无用的信息,保证传输的头部字节数尽量小
小贴士
版权声明:本文标题:《透视 HTTP 协议学习》摘录 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1729143048h1323196.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论