这是一篇关于http的历史故事。HTTP 超文本传输协议(HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。本文不重点介绍http协议中的语法和传输协议的实现。我们只是简单入门,了解这些年http协议的变化,和在互联网的浪潮中发挥的重要作用。
1, 1980年
让我们搭上时光机,回溯的到上个世纪80年代(1980),那个时候tcp/ip模型已经提出,ISO模型差不多在这个时间段提出(1981),因为网络模型的建立,人们之间已经可以通过网络进行通信。然而令人遗憾的是,那个时候HTML标准都还没制定,更别说浏览器。所以像现在这样没事开个网页,看看信息在那个时代还是不存在的。然而在1980年代后期超文本技术已经出现,当时还有国际间的超文本学术会议,每次都有上百篇的有关超文本的论文问世,但没有人能想到把超文本技术应用到计算机网络上来。
2, 1990年
时光荏苒,转眼间10年过去了。一个名叫 Tim Berners-Lee的人横空出世。他在1990年构思了HTML, SGML(标准通用标记语言)的产物。当然那个时候还没有制定一套标准。最重要的是他发明了世界上首个网页浏览器。喜大普奔!!!
1991年,他创建了世界上第一个网页: http://info.cern.ch/hypertext/WWW/TheProject.html 当然,这个网页看上去就很NB,和现在市面上的网页完全不一样。
2.1 http 0.9
与此同时,他还制定了一个协议,基于TCP协议(网络层),位于应用层,用来访问他的网页。大概是这个样子的。
GET /dir/index.html
没错,你没有看错。 这个就是传说中的http协议的最初版本, HTTP 0.9。只有一个GET, 后面跟着需要访问的html网页,只能是html网页,不是资源。然后就会建立TCP链接。
返回的也什么都没有,只有一个html。我们用telnet访问以下本地的apache2服务器。
telnet localhost 80
GET /index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body style="text-align:center">
<h1>启动成功</h1>
</body>
</html>
Connection closed by foreign host.
返回一个html页面。然后关闭链接TCP链接。
2.2 互联网热潮
在1991-1995年,这段时间HTML标准被定义的比较完善,一款叫做浏览器的应用风靡全球,也是在这个时间段内,W3C(万维网联盟)成立了 —— 1994年10月。创立者, 恩,没错,还是那个男人Tim Berners-Lee。而随着互联网的风靡,HTTP/0.9暴露出来的问题也越来越多。首先就是丰富的数据,人们不再想看光秃秃的文字,还想看光鲜亮丽的小姐姐图片,想听音乐… 其次随着越来越多网络应用的出现, http0.9很难担负起这个重任。
2.3 http 1.0
1996年5月。民心所向,http1.0版本发布。相比较0.9,http 1.0的内容大大丰富了。下面就简单介绍一下。
1. 任何格式: 互联网不再是只可以传输文字,还能传输图像、音频,视频、二进制文件的等。
2. http命令:除了GET外还支持POST命令和HEAD命令。当然现在不止支持这些。应该是发展过程加上去的。
3. 请求头和响应头: 除了具有HTTP版本号的请求行,后还需要跟请求标头,响应状态,后跟响应标头,然后是响应正文。请求和响应头都保存为ASCII编码,但响应对象本身可以是任何类型:HTML文件,纯文本文件,图像或任何其他内容类型。
4. 其他常用功能:内容编码,字符集支持,多部分类型,授权,缓存,代理行为,日期格式等。
http/1.0协议的出现,让之前超文本传输协议的变成超媒体传输协议。但是可能是懒的原因,也就没改名了。
http/1.0就和现在的协议很像.但是现在服务器可能都做了优化,发送1.0请求回应都是1.1 ,弄了好久放弃了。例子:
telnet>
GET / HTTP/1.0
User-Agent: User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0)
Accept: */*
HTTP/1.1 200 OK
Date: Thu, 05 Jul 2018 02:55:49 GMT
Server: Apache/2.4.33 (Ubuntu)
Upgrade: h2,h2c
Connection: Upgrade, close
Last-Modified: Wed, 27 Jun 2018 08:42:36 GMT
ETag: "18b-56f9b98ba3b98"
Accept-Ranges: bytes
Content-Length: 395
Vary: Accept-Encoding
Link: </style.css>; rel=preload; as=style
Content-Type: text/html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body style="text-align:center">
<h1>启动成功</h1>
<img hidden src="images/end1.jpg">
</body>
</html>
Connection closed by foreign host.
2.3.1 http/1.0 的请求:
GET / HTTP/1.0
User-Agent: User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0)
Accept: */*
第一行是请求命令,尾部必须添加协议版本HTTP/1.0 -必须大写!。
后跟请求头:
1. User-Agent:用户的浏览器。
2. Accept: 接受的文件格式。 */* 所有文件。
2.3.2 http/1.0 的响应。 因为我没法测试, 就用网上的吧。
HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 01 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 1 May 1996 12:45:26 GMT
Server: Apache 0.84
<html>....</html>
第一行响应格式, 响应状态。
后跟响应头:
1. Content-Type:响应数据。请求头响应头都是ascii码,但是响应数据可以任意,这个就是告知浏览器响应数据的格式式。
2. Content-Length:文件长度。
3. Expires:缓存失效日期
4. Last-Modified: 最后修改时间
5. server: 服务器
再跟响应体。
关闭链接。
2.3.3 笔记:
至今服务器和浏览器都还支持http1.0。但是http1.0继承的0.9的传统,每次请求都需要重新建立连接。这个十分耗费资源。 see: 三次握手,慢启动。而且当时http1.0是没有Keep-Alive属性的。只是在1.1出现之后才追加回去的。
2.4 http 1.1
1997年1月。比1.0仅仅晚了6个月。直接发布了http 1.1。然后在2年半后的1999年6月,对http1.1进行一次更新。然后http 1.1协议至今还在使用。
http 1.1解决了一些歧义问题, 当然引入了最重要的一个东西:KeepAlive连接。还有分包传输,字节范围请求,缓存机制, Host等。http1.1要求必须加上host。
例子:
GET / HTTP/1.0
Host: localhost
User-Agent: User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0)
Accept: */*
HTTP/1.1 200 OK
Date: Thu, 05 Jul 2018 03:32:17 GMT
Server: Apache/2.4.33 (Ubuntu)
Upgrade: h2,h2c
Connection: Upgrade, close
Last-Modified: Wed, 27 Jun 2018 08:42:36 GMT
ETag: "18b-56f9b98ba3b98"
Accept-Ranges: bytes
Content-Length: 395
Vary: Accept-Encoding
Link: </style.css>; rel=preload; as=style
Content-Type: text/html
<!DOCTYPE html>
<html>...</html>
这个请求头和响应头与1.0的语法是一致的。就稍微介绍一下吧。
Host: 指名需要访问的域名。现在一台服务器可以对应多个域名,也就是这个Host给虚拟主机出现提供了支持。
启动的分包传输编码:Transfer-Encoding: chunked
持久连接(Persistent Connection)
http1.1 于 http 1.0 最大的区别在于keepalive,它允许我们重用现有的TCP连接,以便对同一主机发出多个请求。当然,http1.0 后来也添加了这个字段提供长久支持。但是默认是不开启的。而http 1.1 默认开始,而且不需要写这个字段就可以。虽然是长连接,但是只是减少了三次握手次数,请求次数还是有多少html文件,图片,css, js 就需要请求多少次的。
终止这个连接。 客户端和服务器有一方提出关闭,连接就会断开。当然一段时间无响应也会关闭,但是最正确的写法自然是客户端在得到所有资源并不需要新的请求后发送colse请求(Connection: close)。
100状态码
HTTP/1.1加入了一个新的状态码100(Continue)。客户端事先发送一个只带头域的请求,如果服务器因为权限拒绝了请求,就回送响应码401(Unauthorized);如果服务器接收此请求就回送响应码100,客户端就可以继续发送带实体的完整请求了。100 (Continue) 状态代码的使用,允许客户端在发request消息body之前先用request header试探一下server,看server要不要接收request body,再决定要不要发request body。
此外,HTTP/1.1协议添加了内容,编码,字符集,甚至语言协商,传输编码,缓存指令,客户端cookie,以及可以在每个请求上协商的十几种其他功能,还新增了指令:PUT、PATCH、HEAD、 OPTIONS、DELETE。这里就不讲解了。
3, 2009年
从1997年到2009年互联网一直使用的都是http1.1协议。这段时间互联网的发展也是异常迅速,http1.1的一系列的优化也在这段时间出现。在2009年google退出了SPDY 协议,为了解决 HTTP/1.1 效率不高的问题。随后在推行几年的时间内得到广泛认同后,作为http/2的基础。
4, 2012年
随着互联网越来越普及,不论是网上购物,阅读,支付,看视频,听音乐,聊天,新闻等,各式各样的方式使用http1.1协议也显示出了有压力的迹象,http协议也需要进行变革,在2012年初,HTTPbis working group 提出了http/2的计划。
5, 2015年
http/2 协议在2015年正式推出。http/2 协议基本继承了SPDY协议。而且不会再出现2.x的版本。
HTTP / 2(最初命名为HTTP / 2.0)是万维网使用的HTTP网络协议的主要修订版。它源于早期的实验性SPDY协议,最初由谷歌开发。在开放互联网上HTTP 2.0将只用于https://网址,而 http:// 网址将继续使用HTTP/1.x
5.1 HTTP/2
HTTP / 2的重点是提高传输性能并实现更低的延迟和更高的吞吐量。最重要的是,没有任何高级协议语义受到影响:所有HTTP头,值和用法都是和http1.1相同。也就是现有的所有web应用需要转http/2协议不需要修改任何http有关的字段。当然服务器必须支持且开启http/2。
不同的是http/1.x 版本的头字段是ascii码,而数据体可以是任何格式,而http/2不论是头还是数据体都是二进制,帧(Frame):HTTP/2通信的最小单位,每个帧包含帧首部,会标识出当前帧所属的流。消息(Message):由一个或多个帧组合而成,例如请求和响应。
5.1.1 http/2消息发送
在HTTP/2中,数据流以消息的形式发送,而消息由一个或多个帧组成,帧可以在数据流上乱序发送,然后再根据每个帧首部的流标识符重新组装。
5.1.2 多路复用
HTTP/2 在一个tcp连接中,客户端和浏览器可以同时发送多个请求和响应,而且不论顺序。哪怕某个消息处理很耗时,并不会影响其他请求, 因为是以帧的形式发送,而帧的头部记录了所属请求,所以提升了效率。
5.1.3 头部压缩
客户端和服务器共同维护同一张“首部表”,http头部消息会记录在这张表中, 如果已经发过一个请求,第二次请求只会发送修改后的字段,减少冗余数据,降低开销。
5.1.4 服务器推送
服务器除了可以响应客户请求外,还能向客户端推送额外的资源。当然客户端是可以不接受的。虽然看上去很简单,其实这个功能及其强大,比如可以通过客户端发送的请求头,列出需要的资源,服务器一次推送过去, 也就只需要一次http的交互,可以推送n个资源。 当然,资源越多响应越慢,这个看情况而用。
总之http/2协议的能力虽然很强大的,但是http/1.1仍然广泛使用在互联网中。
6, 参考链接
www.ruanyifeng.com/blog/2016/08/http.html