HTTP协议整理分析
有兴趣可以关注我的博客 王二小的博客
认知
维基百科上解释为:超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议[1]。HTTP是万维网的数据通信的基础。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。通过HTTP或者HTTPS协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。
HTTP发展历程
- HTTP/0.9版本,这个时候的HTTP只支持
GET
请求,且不支持请求头, - HTTP/1.0版本,这是第一个在通讯中指定版本号的HTTP协议版本,至今仍被广泛采用,特别是在代理服务器中。
- HTTP/1.1版本,持久连接被默认建立,并能很好地配合代理服务器工作。还支持以管道方式在同时发送多个请求,以便降低线路负载,提高传输速度。
- HTTP/2.0版本,当前版本,于2015年5月作为互联网标准正式发布。
HTTP请求
HTTP
请求第一步,应该是由客户端发起一个HTTP
请求,当然这个客户端可以是例如我们的浏览器,F12调试,发起我们的第一个请求头信息。
假设我们现在开始请求我自己的博客 王二小的博客
你会看到,这是几行文本,这里插一句,HTTP/1.1
沿用的是文本类型的请求头,HTTP/2
则会使用二进制数据。
接下来,我们分析下这个请求
- 第一行: 发送一个
GET
请求,地址是http://www.wedophp.com/
,使用的协议是HTTP/1.1
- 第二行: 标记服务器的
URL
地址 - 第三行: 使用的连接方式,这里的
keep-alive
指的是使用长连接,请记住啊,HTTP/1.1
默认使用的就是长连接,什么是长连接?待会在分析。 - 第四行: 用于随报文传送缓存指示,单位为秒
- 第五行: 我们知道有一个安全的连接
HTTPS
,这种页面的请求中不允许附带HTTP
请求,一旦附带,就会报错,所以有这个以后,浏览器就会自动升级请求。 - 第六行: 本地浏览器的一些信息,以及
IE
版本。 - 第七行: 告诉服务器可以发送哪些媒体类型
- 第八行: 告诉服务器能够发送哪些编码方式
- 第九行: 告诉服务器能够发送哪些语言
- 第十行: 附带本地
cookie
信息,每个cookie
是由一个key
,一个value
形式的,每个key=>value
之后都会有一个空格隔开
HTTP是如何建立连接的
说道如何连接的,我们必须要回顾一个东西,那就是大学学到过的计算机网络基础,几乎所有的大学生
都应该了解过计算机的网络模型,也就是我们熟知的七层网络模型
,如下图
但是计算机网络中的七层模型毕竟是理想中的情况,现实是很少有应用实现了七层模型,一般都是整合其中两个或多个,实现一个四层或者五层的模型。
TCP/IP模型
在这里我们研究的是HTTP
,自然要知道它所处在哪个模型中,答案是应用层
。这里要引入一个TCP\IP
的概念,大家应该知道,TCP
处于传输层,IP
属于网络层,而我们这里所探究的HTTP
,实际上就是基于TCP/IP
协议开发的,至于TCP/IP
的网络模型,它没有照搬计算机网络的七层模型,而是整合了表示层
,会话层
,应用层
,统一为应用层,比较有争议的是,关于TCP/IP
究竟是几层协议,目前为止没有定论,一般我比较习惯统称为四层协议,至于别人说的五层协议,其实就是数据链路层
,物理层
是不是一层有所争议吧。如图:
因为HTTP
是基于TCP/IP
开发的协议,看过HTTP
协议的同学肯定都知道,有句话概述HTTP
协议为无差错的协议
,按序传输
,未分段的数据流
,这其实说的就是TCP
协议。
发送一条HTTP请求会发生什么?
当你在浏览器输入一个URL
的时候,有没有想过这其中发生了什么?
- 获取主机名,例如:
http://www.wedophp.com
- 通过
DNS
获取服务器IP
- 获取端口,默认是80端口
- 连接到
112.23.59.223:80
服务器 (这里其实是TCP
连接) - 通过
TCP
信道发送一个HTTP
请求 - 服务器读取一个
HTTP
请求 - 服务器查找所需资源并通过
TCP
信道返回资源 - 关闭
TCP
连接
HTTP持久连接的问题
我们每次发送一个HTTP
请求,会附带一个Proxy-connection: keep-alive
,这个参数就是声明一个持久连接,那么你会问,什么是持久连接?
持久连接,本质上是客户端与服务器通信的时候,建立一个持久化的TCP
连接,这个连接不会随着请求结束而关闭,通常会保持连接一段时间,至于保持多长时间,则根据你的服务器软件决定,例如nginx
配置文件中可以配置。
为什么要持久连接?通常我们请求一个HTML
文档,文档中不仅仅只有一个请求,包括加载的图片,js,css,加起来的HTTP
请求可能会很多,如果每次请求都去建立一个TCP
连接,势必会造成浪费,如果并发足够,系统资源必定不够用,而持久化连接可以让每个用户尽量少的去建立TCP
连接,从而减少服务器资源开销。
HTTP 管道化连接
HTTP1.1允许在持久连接上可选的使用请求管道,这是相对于持久连接的又一性能优化。
假设请求服务器的一个HTML
资源,这个HTML
中包含很多JS
,CSS
文件,最开始的请求获取HTML
文件,然后等待服务器回传HTML
,客户端拿到了HTML
之后,开始解析,然后请求CSS
,然后是JS
,这个过程是线性的,也就是说客户端发送一个HTTP
请求以后,必须要等待服务器返回结果并且自己接收到完毕以后再发送第二个请求,这样的方式有一个严重的问题,当第一个请求阻塞以后,客户端始终拿不到响应报文,第二个请求也发不出去,导致严重的问题。
何为管道化连接,如图所示:
在响应到达之前,可以将多条请求放入请求对列。当第一条请求通过网络到达服务器的过程中,第二条已经开始发送了,在高时延网络条件下,这样做可以降低网络的环回时间,提高性能。
HTTP的无状态
何为无状态,《用TCP/IP进行网际互联:第三卷 客户端-服务器编程与应用》书中提到过,服务器所维护的与客户端交互活动的信息称为状态信息,不保存任何状态信息的为无状态服务器,否则就是有状态服务器,我们知道HTTP
本身是不保存任何用户的状态信息的,所以HTTP
是无状态的协议
HTTP协议如何保存用户状态?
对于开发比较熟悉的朋友应该知道,HTTP维护一套cookie
和session
体系,即用户第一次访问服务器的时候,服务器响应报头通常会出现一个Set-Cookie
响应头,这里其实就是在本地设置一个Cookie
,当用户再次访问服务器的时候,HTTP
会附带这个Cookie
过去,其实就是一个身份证样的东西,证明我还是刚刚那个小明,我第二次来了,这是我的身份证,服务器看到了你的身份证之后,想起来,你是小明啊,来,这是有关于你的东西,再传递回来。
这里我们先看看一个响应报文