HTTP协议整理分析

HTTP协议整理分析

认知

维基百科上解释为:超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议[1]。HTTP是万维网的数据通信的基础。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。通过HTTP或者HTTPS协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。

HTTP发展历程

  1. HTTP/0.9版本,这个时候的HTTP只支持GET请求,且不支持请求头,
  2. HTTP/1.0版本,这是第一个在通讯中指定版本号的HTTP协议版本,至今仍被广泛采用,特别是在代理服务器中。
  3. HTTP/1.1版本,持久连接被默认建立,并能很好地配合代理服务器工作。还支持以管道方式在同时发送多个请求,以便降低线路负载,提高传输速度。
  4. 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的时候,有没有想过这其中发生了什么?

  1. 获取主机名,例如:http://www.wedophp.com
  2. 通过DNS获取服务器IP
  3. 获取端口,默认是80端口
  4. 连接到 112.23.59.223:80服务器 (这里其实是TCP连接)
  5. 通过TCP信道发送一个HTTP请求
  6. 服务器读取一个HTTP请求
  7. 服务器查找所需资源并通过TCP信道返回资源
  8. 关闭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维护一套cookiesession体系,即用户第一次访问服务器的时候,服务器响应报头通常会出现一个Set-Cookie响应头,这里其实就是在本地设置一个Cookie,当用户再次访问服务器的时候,HTTP会附带这个Cookie过去,其实就是一个身份证样的东西,证明我还是刚刚那个小明,我第二次来了,这是我的身份证,服务器看到了你的身份证之后,想起来,你是小明啊,来,这是有关于你的东西,再传递回来。

这里我们先看看一个响应报文