Web全栈开发:从入门到实战
上QQ阅读APP看书,第一时间看更新

1.2 每一次浏览网页都发生了什么

如今,人人都“挂”在网上,好像上网是一件再平常不过的事儿。只要我们在浏览器地址栏中输入一个网址,便能轻松打开一个网页,这看似极为简单的几秒钟,背后却默默发生了很多事情。要说清楚这背后的原理,我们需要先从网络通信谈起。

1.2.1 通信

众所周知,上网必须要依靠网络才能得以实现。无论你是用手机还是台式机访问网页,都离不开网络的支持。随着数以千万计的网络设备入网,网络这条高速公路变得异常繁忙。在这条高速路上行走的是各式各样的网络设备。包括手机、台式机、笔记本、路由器等。

回想一下,当我们用手机与另一个朋友联系时,双方首先都要有一个电话号码,这个号码就像身份证号一样是唯一的,这样才能保证准确地联系到的是朋友,而不是别人。同样的道理,网络中一台计算机与另一台计算机之间的通信,各自也有“号码”,这个号码称作IP地址。为了保证通信不会出错,这个IP地址必须是唯一的。

每当你打开一个网页时,本质上来说,是你本地的计算机想要和网站运营商的服务器主机通信,目的是请求访问网站相关的所有资源,即一个网页,服务器主机收到请求后,便会立即去寻找,如果一切顺利,它会把所有资源都发送到你所在的本地计算机,最后浏览器负责显示该网页。其中,本地的计算机是客户端(Client),而运营商提供服务的主机是服务器(Server)。

为什么说服务器是一台主机

一般来说,计算机是指一台具有完整上网功能的台式机或笔记本电脑,一般包括显示设备、主机箱、鼠标和键盘等硬件。相对地,主机则只是包含主机箱内的所有核心硬件,而没有像显示器和鼠标等输入、输出设备。因为这些核心硬件就足以完成计算机的核心任务,比如资源的管理,文件和数据的传输和存储等。

大型的网站运营商一般都有自己独立的机房用于存放多台服务器主机,或者租用专用的服务器,用于为邻近的客户端计算机提供服务。

每次打开一个网页时,相当于是客户端与服务器建立了一次通信。这里的通信可以简单理解为一次两者展开的会话,会话开始的标志是从打开浏览器输入网址的那一刻,而结束则代表关闭网页或退出浏览器。为了保证会话的顺利,通信双方要遵循统一的协议,即超文本传输协议(简称HTTP)。该协议规定了通信的双方必须以请求-响应的方式展开,指定客户端能发送什么类型的请求以及服务器端能给出什么响应,以及资源的格式等属性,这些信息以HTTP报文的形式返回给客户端的浏览器。

客户端与服务器端之间的通信过程可以这样理解,当客户端发出对资源的请求时,服务器则负责查找是否存储有请求的资源,如果有,则将与资源相关的所有信息发送给客户端,即对请求做出响应。之后客户端的浏览器会对资源进行缓存并加载,最终网页的内容得以渲染在本地计算机的屏幕上。如果请求的资源不存在,则返回一些提示码(404)和警告信息(资源不存在)。

我要的是网页,为什么说是资源?

其实,浏览器中打开的每一个网页,它的实质是一个HTML文档,又称HTML类型的资源,更进一步来看,该文档通常还包含CSS样式表、图片、JavaScript脚本等文件,这些文件构成了网页上对应类型的资源。因此,当提到浏览器通过地址栏中输入网址请求资源,其本质是根据资源的URL(统一资源定位符)寻找文件,URL用于表示其在本地计算机缓存中(一般是内存)的物理地址或网络服务器主机上的网络地址。

总结一下,一个网页包含多种不同类型的资源,每一个资源都有一个唯一的标识符,浏览器是通过URL请求资源,而服务器则根据URL寻找资源。可见,资源可以是一个HTML文档,也可以是一张图片。

接下来,我们来看看每次通信的过程中发生了什么?

1.2.2 统一资源定位器

在计算机中,所有文件都是依靠目录的方式组织起来的,比如一幅图片的存储路径为D:/web/1.jpg,依靠这个路径,我们就可以很方便地找到该图片。类似地,网络中的所有资源也是依靠同样的方式,只不过它有一个很酷的名字——URL(统一资源定位),它主要用来寻找服务器上存储的资源。那么浏览器中的地址和URL的关系到底是什么呢?这一节我们就来一探究竟。

我们以一个网址http://tech.sina.com.cn/csj/2020-02-11/doc-iimxyqvz1887699.shtml为例,来看看该URL是如何标识一个HTML文档资源的。这个地址可以分解成3块来看:

(1)协议类型(http),这是客户端计算机和服务器主机进行网络通信的基础,双方必须遵守同一个协议才能保证正常通信,否则就是“鸡同鸭讲”,完全不在一个频道。

(2)服务器主机的IP地址和端口号(“tech.sina.com.cn”),这是为了从众多的主机群中找到目标服务器主机,建立一对一的通信。所以,这一串字符对应的是一个服务器主机的域名,它等价于一串IP地址(58.49.227.129)。也就是说,我们既可以通过IP地址也可以通过域名来访问服务器主机。而端口号则是特定的网页程序与外界通信的出口,采用HTTP协议的Web应用通常采用是默认的端口号:80或8080。

端口号一定要有吗?

答案是肯定的。为了回答这个问题,我们从IP地址与端口的关系来说一说。当两台计算机在通信时,IP地址可以帮助我们定位到目标主机,但是由于目标主机上一般运行着多个网络程序,因此,还需要端口号来标识每一个不同的上网程序(进程)。准确来说,要寻找一个特定的网络程序,必须依靠IP地址和端口号的组合。其中,端口号是联网程序(进程)与外界进行通信(比如数据交换)的必经之地。如果做一个比喻的话,IP地址和端口号的关系可以近似为楼栋和楼门号的关系。

回到新浪网的例子,好像网址中并未出现端口号,那是因为在默认情况下,HTTP协议的程序都采用80,这个可以省略。如果有其他非80的端口号,则必须要在地址栏中明确给出。

(3)文件路径(“csj/2020-02-11/doc-iimxyqvz1887699.shtml”),这一串看似复杂,其实逐一分解就会发现其实很简单。首先,从最后doc-iimxyqvz1887699.shtml看,这是一个shtml文档资源,“.”前面的字符串是文件名;接着,“2020-02-11”是该文件存储的文件目录(即一个文件夹);然后,“csj”是上上一级文件目录。它跟在域名之后,表示对于网站站点的根目录的相对路径,说明目标网页文档的存储位置是相对于根目录下的csj/2020-02-11文件夹中。

这就更清楚了,上述地址中的URL对应的是新浪网上一篇文章的网页,它背后的本质是该地址指向存放在新浪的某一台服务器主机上的一个HTML文档。

shtml和html文档是一回事?

其实,一个HTML文档的后缀名有三个,分别是htm、shtml和html。也就是说,看见网页对应的URL的末尾是以它们结尾的话,都代表是对一个HTML文档资源的请求。

其中htm和html完全是一个意思,可以互换。但是为了技术上更容易理解,推荐使用html。

shtml和html对于本地浏览器来说都是HTML格式的静态网页。但有一点不同的是,shtml中多了一些包含SSI技术命令和服务器端指令的语句,这些语句很大的可能是说这些HTML的内容是由服务器端的脚本动态生成的。更多关于静态和动态网页的介绍后面会有更详细地解释,这里不再赘述。

1.2.3 浏览器如何理解网页

前面提到,客户端的浏览器会接收到服务器主机发来的HTTP报文,这些报文信息经过传输和解析后就隐藏在浏览器中。

当你在百度搜索框输入“新浪”(即客户端发送一个HTTP请求到百度服务器),按下F12打开开发者测试工具,找到Network选项,可以看到甘特图下方有一个表格,如图1.2所示。它包含着无数行数据,其实每一行数据都代表着对不同资源的描述。

图1.2

具体来看,每一行中包含一些列属性,这些属性是对资源的描述,属性的具体含义说明如表1.1所示。

表1.1 请求资源的属性说明

续上表

通过表1-1中描述的信息,我们可以知道与网页中包含的所有资源的相关信息,从而有利于做进一步的网页优化。

接着,在Name列,随意选择一个资源单击打开,如图1.3所示的Headers。这里隐藏着更重要的信息,即请求头和数据、响应头和数据。

图1.3

一般来说,一次正常通信的报文头(Headers)包括四部分内容:General、Response Headers、Request Headers和Query String Parameters(可选项)。

(1)General(通用信息)

它是本次请求-响应通信的基本信息,包括请求的新浪网页(Request URL),请求方式是GET,HTTP状态码是200,表示正常,以及远程地址。

(2)Response Headers(响应头部)

这一部分是服务器发出响应的一些重要信息,其中主要的信息字段如表1.2所示。

表1.2

(3)Request Headers(请求头部)

这一部分是关于客户端发出请求相关的一些重要信息,具体包括以下内容:

·Accept:表示能够接受的网页形式,包括text(文本)、JavaScript代码等;

·Cookie:用来存储一些用户信息以便让服务器辨别用户的身份(大多数需要登录的网站上面会比较常见),比如Cookie会存储一些用户的用户名和密码,当用户登录后就会在客户端产生一个Cookie来存储相关信息,这样浏览器通过读取Cookie的信息去服务器上验证,通过后会判定你是合法用户,从而允许查看相应网页;

·Host:发送请求时,这是必须指定的主机和端口号,主机是www.baidu.com,端口号80省略即可;

·Referer:这个一般都会有,告诉服务器我是从哪个页面链接过来的,服务器借此获得一些信息。比如从我主页上链接到一个朋友那里,他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问朋友的网站;

·User-Agent:告诉HTTP服务器,客户端使用的操作系统和浏览器的名称和版本,尝试找找有没有Chrome以及其版本号。我们上网登录论坛的时候,往往会看到一些欢迎信息,其中列出了你的操作系统的名称和版本,你所使用的浏览器的名称和版本,这往往会让很多人感到很神奇,实际上,服务器应用程序就是从User-Agent这个请求报头域中获取到这些信息的;

·X-Requested-With:这个属性用于在服务器端判断前端的请求(Request)是来自Ajax异步请求,还是传统的同步请求。当它为XMLHttpRequest时,表明是异步请求;如果为null,则表明为传统的请求。

(4)Query String Parameters(查询字符参数)

从图1.4可知,由于用户输入了关键字“新浪”,所以它就是我们查询的关键字参数。这里的参数为加了s的复数,表明允许你一次输入多个查询参数,这些参数和值可以用“&”符号连接,比如wd=`新浪`&author=`小红`。

图1.4

基于以上这些隐藏在浏览器中的信息,客户端和服务器的通信才会变得真正可行。

1.2.4 从程序方面理解网页

这一节要从程序的角度来理解一下要想成功打开并显示一个网页,都需要依靠哪些程序来完成。这里还是以在百度主页https://www.baidu.com中搜索“新浪”过程为例,来看看前端采用JavaScript程序和后端采用PHP程序的网页访问和加载过程,客户端与服务器之间的通信见图1.5。

图1.5

图1.5可以分成三个阶段来解读。

(1)客户端发送请求

在同一时段,网络中通常有多台本地主机在浏览器中输入百度的网址,这些请求会首先经过DNS域名解析服务器,负责将提取出来的服务器名称转换成一个IP地址,比如:220.181.38.148,从而去网络中查找该地址对应的百度上的一台服务器主机。

(2)服务器返回响应

服务器主机上一定装有一款Web服务器程序(比如Apache),它通过遵守HTTP(超文本传输协议)与客户端浏览器进行信息交流,并负责存放目标资源的相关文件。一旦用户在百度的搜索框内输入“新浪”,服务器很快便去搜索与关键词新浪相关的HTML文档、CSS样式表、图片以及JavaScript程序。由于搜索的部分结果可能是从数据库中动态查询到的,所以在JavaScript程序中,还会通过服务器端的PHP脚本程序,该程序一般放在PHP应用服务器上,主要实现对数据库的查询,而数据库一般是以一个数据库管理系统程序的形式出现。

在通信正常且请求成功的情况下,新浪相关的查询结果会返回给PHP程序,接着它又把结果告诉JavaScript程序。

(3)浏览器解析代码并渲染网页内容

JavaScript程序会在浏览器中解析和执行,随着搜索结果的相关资源下载到本地缓存中,网页中相关的CSS样式和JavaScript程序也会异步加载,最终会成功渲染(即网页内容是以画图的方式显示在屏幕上)到网页中,即搜索结果页面展现在操作者面前。

在网页内容的加载过程中,文字和CSS样式会首先显示在页面上,图片和视频等消耗更多网络资源的加载时间比较长,这就是为什么当网络环境不好时,你可能只看到一些文字,图片却没有正常显示或显示不全。