HTTP 协议是互联网的基础协议,也是网页开发的必备知识,最新版本 HTTP/2 更是让它成为技术热点。

本文介绍 HTTP 协议的历史演变和设计思路。

一、HTTP/0.9

HTTP 是基于 TCP/IP 协议的应用层协议。它不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口。

最早版本是1991年发布的0.9版。该版本极其简单,只有一个命令GET


GET /index.html

上面命令表示,TCP 连接(connection)建立后,客户端向服务器请求(request)网页index.html

协议规定,服务器只能回应HTML格式的字符串,不能回应别的格式。


<html>
<body>Hello World</body>
</html>

服务器发送完毕,就关闭TCP连接。

二、HTTP/1.0

2.1 简介

1996年5月,HTTP/1.0 版本发布,内容大大增加。

首先,任何格式的内容都可以发送。这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。这为互联网的大发展奠定了基础。

其次,除了GET命令,还引入了POST命令和HEAD命令,丰富了浏览器与服务器的互动手段。

再次,HTTP请求和回应的格式也变了。除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据。

其他的新增功能还包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等。

2.2 请求格式

下面是一个1.0版的HTTP请求的例子。


GET / HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*

可以看到,这个格式与0.9版有很大变化。

第一行是请求命令,必须在尾部添加协议版本(HTTP/1.0)。后面就是多行头信息,描述客户端的情况。

2.3 回应格式

服务器的回应如下。


HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84 <html>
<body>Hello World</body>
</html>

回应的格式是"头信息 + 一个空行(\r\n) + 数据"。其中,第一行是"协议版本 + 状态码(status code) + 状态描述"。

2.4 Content-Type 字段

关于字符的编码,1.0版规定,头信息必须是 ASCII 码,后面的数据可以是任何格式。因此,服务器回应的时候,必须告诉客户端,数据是什么格式,这就是Content-Type字段的作用。

下面是一些常见的Content-Type字段的值。

  • text/plain
  • text/html
  • text/css
  • image/jpeg
  • image/png
  • image/svg+xml
  • audio/mp4
  • video/mp4
  • application/javascript
  • application/pdf
  • application/zip
  • application/atom+xml

这些数据类型总称为MIME type,每个值包括一级类型和二级类型,之间用斜杠分隔。

除了预定义的类型,厂商也可以自定义类型。


application/vnd.debian.binary-package

上面的类型表明,发送的是Debian系统的二进制数据包。

MIME type还可以在尾部使用分号,添加参数。


Content-Type: text/html; charset=utf-8

上面的类型表明,发送的是网页,而且编码是UTF-8。

客户端请求的时候,可以使用Accept字段声明自己可以接受哪些数据格式。


Accept: */*

上面代码中,客户端声明自己可以接受任何格式的数据。

MIME type不仅用在HTTP协议,还可以用在其他地方,比如HTML网页。


<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<!-- 等同于 -->
<meta charset="utf-8" />

2.5 Content-Encoding 字段

由于发送的数据可以是任何格式,因此可以把数据压缩后再发送。Content-Encoding字段说明数据的压缩方法。


Content-Encoding: gzip
Content-Encoding: compress
Content-Encoding: deflate

客户端在请求时,用Accept-Encoding字段说明自己可以接受哪些压缩方法。


Accept-Encoding: gzip, deflate

2.6 缺点

HTTP/1.0 版的主要缺点是,每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。

TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(slow start)。所以,HTTP 1.0版本的性能比较差。随着网页加载的外部资源越来越多,这个问题就愈发突出了。

为了解决这个问题,有些浏览器在请求时,用了一个非标准的Connection字段。


Connection: keep-alive

这个字段要求服务器不要关闭TCP连接,以便其他请求复用。服务器同样回应这个字段。


Connection: keep-alive

一个可以复用的TCP连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段,不同实现的行为可能不一致,因此不是根本的解决办法。

三、HTTP/1.1

1997年1月,HTTP/1.1 版本发布,只比 1.0 版本晚了半年。它进一步完善了 HTTP 协议,一直用到了20年后的今天,直到现在还是最流行的版本。

3.1 持久连接

1.1 版的最大变化,就是引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive

客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送Connection: close,明确要求服务器关闭TCP连接。


Connection: close

目前,对于同一个域名,大多数浏览器允许同时建立6个持久连接。

3.2 管道机制

1.1 版还引入了管道机制(pipelining),即在同一个TCP连接里面,客户端可以同时发送多个请求。这样就进一步改进了HTTP协议的效率。

举例来说,客户端需要请求两个资源。以前的做法是,在同一个TCP连接里面,先发送A请求,然后等待服务器做出回应,收到后再发出B请求。管道机制则是允许浏览器同时发出A请求和B请求,但是服务器还是按照顺序,先回应A请求,完成后再回应B请求。

3.3 Content-Length 字段

一个TCP连接现在可以传送多个回应,势必就要有一种机制,区分数据包是属于哪一个回应的。这就是Content-length字段的作用,声明本次回应的数据长度。


Content-Length: 3495

上面代码告诉浏览器,本次回应的长度是3495个字节,后面的字节就属于下一个回应了。

在1.0版中,Content-Length字段不是必需的,因为浏览器发现服务器关闭了TCP连接,就表明收到的数据包已经全了。

3.4 分块传输编码

使用Content-Length字段的前提条件是,服务器发送回应之前,必须知道回应的数据长度。

对于一些很耗时的动态操作来说,这意味着,服务器要等到所有操作完成,才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用"流模式"(stream)取代"缓存模式"(buffer)。

因此,1.1版规定可以不使用Content-Length字段,而使用"分块传输编码"(chunked transfer encoding)。只要请求或回应的头信息有Transfer-Encoding字段,就表明回应将由数量未定的数据块组成。


Transfer-Encoding: chunked

每个非空的数据块之前,会有一个16进制的数值,表示这个块的长度。最后是一个大小为0的块,就表示本次回应的数据发送完了。下面是一个例子。


HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked 25
This is the data in the first chunk 1C
and this is the second one 3
con 8
sequence 0

3.5 其他功能

1.1版还新增了许多动词方法:PUTPATCHHEAD、 OPTIONSDELETE

另外,客户端请求的头信息新增了Host字段,用来指定服务器的域名。


Host: www.example.com

有了Host字段,就可以将请求发往同一台服务器上的不同网站,为虚拟主机的兴起打下了基础。

3.6 缺点

虽然1.1版允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为"队头堵塞"(Head-of-line blocking)。

为了避免这个问题,只有两种方法:一是减少请求数,二是同时多开持久连接。这导致了很多的网页优化技巧,比如合并脚本和样式表、将图片嵌入CSS代码、域名分片(domain sharding)等等。如果HTTP协议设计得更好一些,这些额外的工作是可以避免的。

四、SPDY 协议

2009年,谷歌公开了自行研发的 SPDY 协议,主要解决 HTTP/1.1 效率不高的问题。

这个协议在Chrome浏览器上证明可行以后,就被当作 HTTP/2 的基础,主要特性都在 HTTP/2 之中得到继承。

五、HTTP/2

2015年,HTTP/2 发布。它不叫 HTTP/2.0,是因为标准委员会不打算再发布子版本了,下一个新版本将是 HTTP/3。

5.1 二进制协议

HTTP/1.1 版的头信息肯定是文本(ASCII编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为"帧"(frame):头信息帧和数据帧。

二进制协议的一个好处是,可以定义额外的帧。HTTP/2 定义了近十种帧,为将来的高级应用打好了基础。如果使用文本实现这种功能,解析数据将会变得非常麻烦,二进制解析则方便得多。

5.2 多工

HTTP/2 复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了"队头堵塞"。

举例来说,在一个TCP连接里面,服务器同时收到了A请求和B请求,于是先回应A请求,结果发现处理过程非常耗时,于是就发送A请求已经处理好的部分, 接着回应B请求,完成后,再发送A请求剩下的部分。

这样双向的、实时的通信,就叫做多工(Multiplexing)。

5.3 数据流

因为 HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。

HTTP/2 将每个请求或回应的所有数据包,称为一个数据流(stream)。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪个数据流。另外还规定,客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。

数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2 可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。

客户端还可以指定数据流的优先级。优先级越高,服务器就会越早回应。

5.4 头信息压缩

HTTP 协议不带有状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,比如CookieUser Agent,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。

HTTP/2 对这一点做了优化,引入了头信息压缩机制(header compression)。一方面,头信息使用gzipcompress压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。

5.5 服务器推送

HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送(server push)。

常见场景是客户端请求一个网页,这个网页里面包含很多静态资源。正常情况下,客户端必须收到网页后,解析HTML源码,发现有静态资源,再发出静态资源请求。其实,服务器可以预期到客户端请求网页后,很可能会再请求静态资源,所以就主动把这些静态资源随着网页一起发给客户端了。

出处:http://www.ruanyifeng.com/blog/2016/08/http.html

【协议】3、HTTP 协议入门的更多相关文章

  1. ARP协议与ARP攻击入门

    一 ARP协议 ARP协议是一个年代相当"久远"的网络协议.ARP协议制定于1982年11月,英文全称:Address Resolution Protocol,即"地址解 ...

  2. TCP/IP协议学习(四) 协议概述

    生活中有舒适区,借口成为懒惰的护身符,学习也有舒适区,逃避便是阻止进步的最大障碍. 经过半年多嵌入式方面的工作和学习,我提高了很多,但同时我也对自己所面临的问题逐渐清晰: 1. 偏于实践,理论基础不牢 ...

  3. 【转】SSL协议、SET协议、HTTPS简介

    一.SSL协议简介 SSL是Secure Socket Layer的缩写,中文名为安全套接层协议层.使用该协议后,您提交的所有数据会首先加密后,再提交到网易邮箱,从而可以有效防止黑客盗取您的用户名.密 ...

  4. TCP协议与UDP协议的区别

    TCP协议与UDP协议的区别(转) 首先咱们弄清楚,TCP协议和UCP协议与TCP/IP协议的联系,很多人犯糊涂了,一直都是说TCP/IP协议与UDP协议的区别,我觉得这是没有从本质上弄清楚网络通信! ...

  5. Http协议与TCP协议简单理解(转)

    在C#编写代码,很多时候会遇到Http协议或者TCP协议,这里做一个简单的理解.TCP协议对应于传输层,而HTTP协议对应于应用层,从本质上来说,二者没有可比性.Http协议是建立在TCP协议基础之上 ...

  6. TCP协议总结--停止等待协议,连续ARQ协议,滑动窗口协议

    前言:在学习tcp三次握手的过程之中,由于一直无法解释tcpdump命令抓的包中seq和ack的含义,就将tcp协议往深入的了解了一下,了解到了几个协议,做一个小结. 先来看看我的问题: 这是用tcp ...

  7. 在网络7层协议中,如果想使用UDP协议达到TCP协议的效果,可以在哪层做文章?(QQ 为什么采用 UDP 协议,而不采用 TCP 协议实现?)

    为了解决这题,可以具体看看下面这个讨论. 解灵运工程师 185 人赞同 某次架构师大会上那个58同城做即时通信的人说:原因是因为当时没有epoll这种可以支持成千上万tcp并发连接的技术,所以他们使用 ...

  8. ARP缓存表的构成ARP协议全面实战协议详解、攻击与防御

    ARP缓存表的构成ARP协议全面实战协议详解.攻击与防御 1.4.3  ARP缓存表的构成 在局域网的任何一台主机中,都有一个ARP缓存表.该缓存表中保存中多个ARP条目.每个ARP条目都是由一个IP ...

  9. RTSP协议、RTMP协议、HTTP协议的区别

    理论上RTSP RTMPHTTP都可以做直播和点播,但一般做直播用RTSP RTMP,做点播用HTTP.做视频会议的时候原来用SIP协议,现在基本上被RTMP协议取代了. RTSP. RTMP.HTT ...

  10. 转:XMPP协议、MQTT协议、HTTP协议、CoAP协议的基本比较

    一.先看下相关国外的专业数据对四大协议的比较: Protocol                                    CoAP                         XMP ...

随机推荐

  1. 04-jQuery的属性操作

    jquery的属性操作模块分为四个部分:html属性操作,dom属性操作,类样式操作和值操作 html属性操作:是对html文档中的属性进行读取,设置和移除操作.比如attr().removeAttr ...

  2. Visual Studio Code 写Python 代码

    最近在博客园新闻里面看到微软发布的Visual Studio Code 挺好用的,现在在学习Python,查看官网发布的VSCode 是支持Python代码,自己试着安装用一下,下面是我的安装以及配置 ...

  3. 简单的Poc Exp编写(上)

    简单的POC EXP 编写 (上)   作者BY Greekn   今天主要讲的 是关于web 方面的 poc 编写 关于web 安全 个人理解的话 一个就是攻击  另一个就是漏洞挖掘了 防御的话 看 ...

  4. MySQL:change buffer

    1. 概念 Innodb维护了一个缓存区域叫做Buffer Pool,用来缓存数据和索引在内存中.其大小通过参数 innodb_buffer_pool_size 控制: change buffer 是 ...

  5. app操作的一些命令

    这里的操作都是在windows下,在android SDK安装好之后就可以连接实体手机或者模拟器操作 1.查看连接的手机或者模拟器 adb devices 结果如下: 2.查看某个app的包名和act ...

  6. VMware12 安装 Ubuntu18.04

    安装Ubuntu18.04虚拟机 Ubuntu获取地址: 官网:https://www.ubuntu.com/download/server 清华镜像站:https://mirrors.tuna.ts ...

  7. mysql的binlog进行数据恢复

    什么是binlog? binlog,也称为二进制日志,记录对数据发生或潜在发生更改的SQL语句,并以二进制的形式保存在磁盘中,可以用来查看数据库的变更历史(具体的时间点所有的SQL操作).数据库增量备 ...

  8. Mysql插入中文的字段内容时乱码的解决方法

    Mysql插入中文的字段内容时乱码的解决方法 1.我们在往数据库插入数据的时候,当遇到中文字符的插入时会发现插入的数据会变为?号,也就是乱码,如下所示: 2.这时候我们使用如下的查询语句可以看到相应的 ...

  9. springmvc的异步处理

         关于异步的好处我在这里就不多说了,自从servlet3.1规范发布以来,控制层的异步处理也越来越多的被人提及.而Spring5的webflux诞生也意味着Spring全方位对异步提供了支持. ...

  10. mysql 开发进阶篇系列 26 数据库RPM安装演示

    一.概述 上一章讲到了RPM安装后的文件目录,这章还是介绍下安装步骤.也便以后做参考吧. 1. 移出centos 7系统自带的mysql库 yum remove mysql-libs 2. 将下载的m ...