由互联网到万维网
在TCP、UDP协议之后,两台位于不同地域的计算机就可以进行通信了, 这是个了不起的特性,我在上海跟在河南的父母发消息,可比古代六百里加急还要快,但是在应用层的协议、万维网到来之前,互联网还和普通人比较遥远,像是一颗刚发了芽的种子,谁也不会想到在不久的将来,整个世界都将笼罩在它的荫凉之下。
TCP协议发表于1981年,即使传输层提供了可靠传输服务,上面悬浮的应用也比较少,在我国也就用于政府、科研单位快速的传递信息,但是传递信息的方式似乎也比较单一,信息之间没有建立起连接,这一点可以从中国科学院高能物理研究所的网络发展中大致看到,1986年以长途电话线为介质,实现了高能所与西欧中心CERN之间的电子邮件的传输,学者们之间的通信资料,没被连接起来。你对我的研究资料比较感兴趣,你发封邮件给我,然后我把邮件发给你。似乎当时的人们将互联网当成了新时代的信鸽,用来传递一些关键的信息。直到万维网的出现,通过超链接这种媒介,互联网中各个孤立的信息才被建立强连接,实现从一个信息跳转到另一个信息。
写到这里想起我大学的时候,在学习《计算机网络》这门课程的时候,看到万维网这一节,说实话当时我看的似懂非懂的,我不知道什么叫万维网,即使我打开浏览器输入网址,浏览网站信息已经很熟练了,但我也没意识到我当时用的是万维网,我认为那就是互联网,也许在我眼里点击网站链接跳到另一个网站是以一个理所当然的操纵,当时我的计算机网络学的真的是一团糟,我后面对网络认知的加深全是写程序的时候遇到问题,然后去查资料。悄悄的吐槽一下,我大学的时候的教材翻译是着实有些拗口,我觉得我读不懂也正常,介绍万维网是这么介绍的:
万维网WWW(World Wide Web)并非某种特殊的计算机网络,万维网是一个大规模的、联机式的信息储藏所。简称为WEB。
当时的我没有把万维网和日常浏览的网站联系起来,(这也跟我当初听课听不懂,后面就放弃了有关系,其实后面有讲到浏览器,只不过用的描述语让我无论如何都没有跟我日常浏览的网站联系起来),所以我只看懂了前半句:万维网WWW(World Wide Web)并非某种特殊的计算机网络,万维网是一个大规模是。信息储藏所我是看不大懂的,更不用提后面的超文本了、URL之类的了。
我这里想引入另一种视角来介绍万维网,从 Tim Berners-Lee的设计万维网的缘起谈起,即为信息建立连接。Tim Berners Lee进入欧洲原子核研究所,当时的科学家迫切需要一个方便快速的平台来帮助他们远程沟通交换数据,基于这个问题,Tim Berners Lee 设计了万维网,我猜想最初浏览器访问的网址存放的就是原子核研究所的研究资料(查了很久,这方面的资料比较难找,有时间会尝试写一下Web简史),各个文档还是孤立的,那为各个文档建立连接,面临的问题有哪些呢?
- 怎样标志分布在互联网上的万维网文档?
- 用怎样的协议来实现万维网上各个文档上的连接?
- 怎样实现在不同的计算机上实现统一的显示效果呢?
为了解决第一个问题,万维网使用URL来标识万维网上的各种文档(网页),并使每一个文档在整个互联网的范围内具有唯一的标识符(URL)。粗略的说URL=IP:端口/路径。第二个问题就引出了我们的HTTP协议, 第三个问题的答案就是HTML,统一格式、语法。
由万维网到HTTP协议
HTTP协议概述
HTTP译为超文本传送协议,这个超文本可以理解为不止是文本,可以传送图像、视频,最初只是能是静态的。HTTP协议规定了浏览器(客户端进程)怎样向万维网服务器请求万维网文档,以及服务器怎样把文档传送给浏览器。
上面这张图片来自火狐开发者文档。
从层次的角度来讲,HTTP协议是面向事务的,面向事务的意思是一系列信息交换要么全部成功,只要有一次交换失败就全部失败。每个网站都有一个服务器进程不断的监听TCP的端口80, 以便发现是否有浏览器(或其他客户端)向它发出连接建立请求,一旦监听到连接建立请求并建立了TCP连接之后,浏览器就向服务器发起HTTP请求,服务器根据请求响应对应的资源。最后,TCP链接就被释放了。在浏览器和服务器之间的请求和响应的交互必须按照规定的格式和遵循一定的规则,这些规则和格式就是HTTP协议。
它是在 Web 上进行数据交换的基础,是一种 client-server 协议,也就是说,请求通常是由像浏览器这样的接受方发起的。一个完整的Web文档通常是由不同的子文档拼接而成的,像是文本、布局描述、图片、视频、脚本等等
HTTP协议由于运输层选取的是面向连接的TCP协议,保证了数据的可靠传输,但是,HTTP协议是本身是无连接的,这就是说,虽然HTTP使用了TCP连接,但通信的双方在交换HTTP报文之前不需要先建立HTTP连接。
HTTP在应用的早期阶段非常简单,简单的甚至没有版本号, 后来它的版本号被定位在0.9以区分后来的版本。HTTP/0.9极其简单: 请求由单行指令构成, 以唯一可用方法GET开头,其后跟目标资源的:
GET /mypage.html
响应也极其简单: 只包含响应文档本身。
<HTML> 这是一个非常简单的HTML页面 </HTML>
后来被称为HTTP/0.9, 有时也被叫做单行(one-line)协议,跟后来的版本不同,HTTP/0.9 的响应内容并不包含HTTP头,这意味着只有HTML文件可以传送,无法传输其他类型的文件;也没有状态码或错误代码:一旦出现问题,一个特殊的包含问题描述信息的HTML文件将被发回,供人们查看。
随着万维网的不断发展,浏览器和服务器迅速扩展其用途更广, HTTP/0.9版本就有点跟不上时代的发展了, 随后就推出了HTTP/1.0版本:
- 协议版本信息现在会随着每个请求发送(
HTTP/1.0
被追加到了GET
行)。 - 状态码会在响应开始时发送,使浏览器能了解请求执行成功或失败,并相应调整行为(如更新或使用本地缓存)。
- 引入了HTTP头的概念,无论是对于请求还是响应,允许传输元数据,使协议变得非常灵活,更具扩展性。
- 在新HTTP头的帮助下,具备了传输除纯文本HTML文件以外其他类型文档的能力(凭借Content-Type头)
现在的浏览器通过开发者工具可以清楚的看到请求和响应报文:
虽然HTTP/2.0版本已经推出来了, 但是目前国内普遍使用的还是HTTP/1.1协议, 那HTTP 1.1 版本相对于HTTP/1.0版本增加了什么呢?在HTTP1.0版本中,在客户端(通常指浏览器)与服务器能够交互(客户都按发起请求, 服务器返回响应)之前, 必须在这两者之间建立一个TCP链接,打开一个TCP连接需要多次往返交互消息(因此耗时)。HTTP/1.0默认为每一对HTTP/响应都打开一个单独的TCP连接。当连续发起多个请求时,这种模式比多个请求共享一个TCP链接更低效。
连接管理是一个HTTP的关键话题, 在HTTP/1.1里有多种模型: 短连接、长连接, HTTP 流水线。
HTTP的传输协议主要依赖于TCP来提供从客户端到服务端之间的连接。在早期,HTTP使用一个简单的模型来处理这样的连接,但是打开每一个TCP连接都是相当耗费资源的操作。现代浏览器往往要发起很多次请求才能拿到所需的完整信息。为了解决HTTP/1.0的性能问题,HTTP引入了流水线和长连接模型。HTTP的长连接有的时候也被称为Keep-alive连接,一个长连接会保持一段时间,重复用于发送一系列的请求,节省了新建TCP连接握手的时间,还可以利用TCP的性能增强能力。当然这个连接不会一直保留, 连接在空闲一段时间后会被关闭(服务器端可以使用Keep-Alive协议头来指定一个最小的连接保持时间)。
但是长连接也并非完美无缺,因为就算是空闲状态 ,它还是会消耗服务器的资源,而且在高负载时,还有可能遭受DoS Attacks 攻击。在这种场景下,可以使用非长连接,即尽快关闭那些空闲的连接,也能对性能有所提升。
HTTP/1.0默认并不使用长连接,在HTTP/1.1里默认就是长连接,协议头都不用再去声明它。HTTP 流水线在现代浏览器中并不是默认被启用, 因为它难以实现。要讲清楚为什么难以实现也并不是一个简单的问题,我们会调一篇文章专门讲这个难以实现的原因。这里我们只简单的介绍一下它的实现: 默认情况下,HTTP请求是按顺序发出的,下一个请求只要在当前请求收到应答过后才会发出,由于会受到网络延迟和带宽的限制,在下一个请求被发送到服务器之前,可能需要等待很长时间。
流水线是在同一条长连接上发出的连续请求,而不用等待应答返回。这样可以避免连接延迟。但不是所有类型的HTTP请求能用到流水线。
值得注意的是HTTP/1.0多种不同的实现方式在实际运用中显得有些混乱,自1995年开始,即HTTP/1.0文档发布的下一年,就开始修订HTTP的第一个标准化版本。在1997年初,HTTP1.1标准发布,就在HTTP/1.0发布几个月后。
下面我们通过浏览器的开发者工具观察报文,来介绍HTTP1.0-1.1的引入的新特性:
- 引入了HTTP头的概念,无论是对于请求还是响应,允许传输元数据,使协议变得非常灵活,更具扩展性。
- 在新HTTP头的帮助下,具备了传输除纯文本HTML文件以外其他类型文档的能力(凭借Content-type头)。
- 引入内容协商机制,包括语言,编码,类型等,并允许客户端和服务器之间约定以最合适的内容进行交换
请求报文与响应报文概述
如上图所示上面是一个典型的HTTP请求报文的请求头, method 可以理解为HTTP的一个请求报文类型,HTTP协议中有好几种不同的请求报文类型:
- CONNECT
- DELETE
- GET
- HEAD
- OPTIONS
- PATCH
- POST
- PUT
- TRACE
粗略的说请求报文用于向服务器说明,我这次需要什么样的资源,请你返回给我。不同的请求方式用于请求不同的资源。响应报文用于说明我们返回了什么资源,请你接收。
下面是一个响应报文:
我们可以看到上面说的content-type,就是在告诉客户端我返回给你的是json, 按照这个方式来解析。HTTP的状态码用于指明这次HTTP通信的状态:
- 1xx 表示通知信息
- 2xx 表示成功
- 3xx 表示重定向, 如要完成请求还必须采取进一步的行动。
- 4xx 表示客户端的差错,如请求中有错误的语法不能完成。
- 5xx 表示服务器的差错, 如服务器失效无法完成请求。
至此我们已经完成了对HTTP协议的大致介绍,为了连接互联网上的信息,万维网的先驱Tim Berners-Lee设计了HTTP协议,为了统一显示效果,引入了HTML,为了标记文档,引入了URL。在HTTP协议中请求报文用于说明向服务端请求获取的资源,响应报文是请求的获取资源加一些控制信息,状态码用于指明此次 通信的状态。世界已经被万维网改变了模样,即使你不知道万维网的发明者蒂姆•伯纳斯•李。