一、在浏览器地址栏输入URL
当我们开始在浏览器中输入网址的时候,浏览器其实就已经在智能的匹配到你想要的 URL 了,它会从历史记录,书签等地方,找到已经输入的字符串可能对应的 url,然后给出智能提示,让你可以补全 URL 地址。
URL是什么
URL是 Uniform Resource Locator 的缩写,翻译过来就是统一资源定位符,俗称网址。它是对网络资源的引用,指定了其在计算机网络的位置以及用于检索它的机制。如同在网络上的门牌,是因特网上标准的资源的地址(Address)。URL通常用于引用网页(http),但也用于文件传输(ftp),电子邮件(mailto),数据库访问(JDBC)以及许多其他应用程序。
统一资源定位符的标准格式如下:
scheme:[//host[:port]][/path][?query][#fragment]
协议类型:[//服务器地址[:端口号]][/资源层级UNIX文件路径]文件名[?查询][#片段ID]
统一资源定位符的完整格式如下:
scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]
协议类型:[//[访问资源需要的凭证信息@]服务器地址[:端口号]][/资源层级UNIX文件路径]文件名[?查询][#片段ID]
1.协议类型:最常见的有http、https、ftp、file 协议
2.层级URL标记符号:为[//],固定不变
3.访问资源需要的凭证信息(可省略)
4.服务器地址:通常为域名,有时为IP地址
5.端口号:以数字方式表示,若为HTTP的默认值“:80”(可省略)
6.路径:以“/”字符区别路径中的每一个目录名称。
7.查询:GET模式的窗体参数,以“?”字符为起点,每个参数以“&”隔开,再以“=”分开参数名称与数据,通常以UTF8的URL编码,避开字符冲突的问题
8.片段:以“#”字符为起点
其中:
1. http,是协议;
2. zh.wikipedia.org,是服务器地址;
3. 80,是服务器上的网络端口号;
4. /w/index.php,是路径;
5. ?title=Special:%E9%9A%8F%E6%9C%BA%E9%A1%B5%E9%9D%A2&printable=yes,是询问。
大多数网页浏览器不要求用户输入网页中“http://”的部分,因为绝大多数网页内容是超文本传输协议文件。同样,“80”是超文本传输协议文件的常用端口号,因此一般也不必写明。一般来说用户只要键入统一资源定位符的一部分(zh.wikipedia.org/wiki/Special:%E9%9A%8F%E6%9C%BA%E9%A1%B5%E9%9D%A2)就可以了。
协议类型
最常见的协议类型有: http、https、ftp、file 协议
FILE - File本地文件查找协议,资源是本地计算机上的文件。格式 file:///文件路径,例如: file:///Users/hunger/workspace/a.html
FTP - 文件传输协议(英文:File Transfer Protocol,缩写:FTP)是用于在网络上进行文件传输的一套标准协议,使用客户/服务器模式。它属于网络传输协议的应用层。 刑如 ftp://ftp.gimp.org/
HTTP - 超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议[1]。HTTP是万维网的数据通信的基础。
HTTPS - HTTP安全(HTTPS)是超文本传输协议(HTTP)的改进,用于在计算机网络上进行安全通信,并且在互联网上被广泛使用。 与HTTP的URL由“http://”起始且默认使用端口80不同,HTTPS的URL由“https://”起始且默认使用端口443。
mailto - mailto是电子邮件地址的统一资源标识符(URI)方案。它被用来在网站上制作超链接,允许用户发送电子邮件到一个特定的地址,输入邮件地址时不必将 mailto: 输入到电子邮件客户端。 格式 mailto:someone@example.com
其他的日后补充。。。
二、浏览器查找域名的IP地址
IP地址
互联网协议地址(Internet Protocol Address),是分配给网络上使用网际协议的设备的数字标签。常见的IP地址分为IPv4与IPv6两大类。IP地址是唯一的。每个处于互联网中的设备都有IP 地址,形如192.168.0.1
域名
IP地址是Internet主机的作为路由寻找地址用的数字体标识,人不容易记忆。因而产生了域名这一种字符型标识。域名(Domain Name)是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。域名的目的是便于记忆和沟通的一组服务器的地址(网站,电子邮件,FTP等)。
DNS
网域名称系统(Domain Name System)是因特网的一项核心服务,它作为可以将域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网,而不用去记住能够被机器直接读取的IP地址数串。例如,www.wikipedia.org,是一个域名,和IP地址 208.80.152.2 相对应。DNS就像是一个自动的电话号码簿,我们可以直接拨打 wikipedia 的名字来代替电话号码(IP地址)。我们直接调用网站的名字以后,DNS就会将便于人类使用的名字(如www.wikipedia.org)转化成便于机器识别的IP地址(如208.80.152.2)。
实际上DNS就是一组键值对,键名就是域名,值就是IP地址。
域名解析
浏览器缓存 – 如果之前访问过,浏览器会缓存DNS记录一段时间,浏览器自行决定缓存的时间。
系统缓存 - 如果浏览器缓存里没有记录,浏览器会从系统调用,从 Hosts 文件查找是否有该域名和对应 IP。
路由器缓存 – 一般路由器也会缓存域名信息。
ISP DNS 缓存 – 比如到电信的 DNS服务器 上查找缓存。
我们使用的 ISP 的 DNS 记录里面如果还没有的话,那么就会向根域名服务器继续查询,(例如google.com)从根域名服务器 通过COM顶级域名服务器,到google.com 域名服务器,指到查询到IP 地址为止。
其他知识扩展,请参考【原】老生常谈-从输入url到页面展示到底发生了什么
三、浏览器向Web服务器发送HTTP请求
简单来说,浏览器找到域名对应的IP地址后,将会建立TCP连接,通过TCP协议发送一个HTTP请求到Web服务器,HTTP请求里会包含请求信息,Web服务器接收之后处理请求并返回响应。
HTTP通信机制是在一次完整的HTTP通信过程中,Web浏览器与Web服务器之间将完成下列7个步骤:
(1)建立TCP连接
在HTTP工作开始之前,Web浏览器首先要通过网络与Web服务器建立连接,该连接是通过TCP来完成的,该协议与IP协议共同构建Internet,即著名的TCP/IP协议族,因此Internet又被称作是TCP/IP网络。HTTP是比TCP更高层次的应用层协议,根据规则,只有低层协议建立之后才能,才能进行更高层协议的连接。因此,首先要建立TCP连接,一般TCP连接的端口号是80。
有兴趣了解关于建立TCP连接过程可以参考 TCP建立连接三次握手和释放连接四次握手
(2)Web浏览器向Web服务器发送请求命令
一旦建立了TCP连接,Web浏览器就会向Web服务器发送请求命令
例如:GET/sample/hello.jsp HTTP/1.1
(3)Web浏览器发送请求头信息
浏览器发送其请求命令之后,还要以头信息的形式向Web服务器发送一些别的信息,之后浏览器发送了一空白行来通知服务器,它已经结束了该头信息的发送。
(4)Web服务器应答
客户机向服务器发出请求后,服务器会客户机回送HTTP应答,
HTTP/1.1 200 OK
应答的第一部分是协议的版本号和应答状态码
(5)Web服务器发送应答头信息
正如客户端会随同请求发送关于自身的信息一样,服务器也会随同应答向用户发送关于它自己的数据及被请求的文档。
(6)Web服务器向浏览器发送数据
Web服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此为结束,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据。
(7)Web服务器关闭TCP连接
一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接。如果浏览器或者服务器在其头信息加入了这行代码
Connection:keep-alive
TCP连接在发送请求后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。
HTTP请求格式
下面是一个完整的HTTP请求例子:
GET/sample.jspHTTP/1.1
Accept:image/gif.image/jpeg,*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)
Accept-Encoding:gzip,
// 空行
deflate username=jinqiao&password=1234
注意:最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。
(1)请求的第一行是“请求方法/URL 协议版本”:GET/sample.jsp HTTP/1.1
URL完整地指定了要访问的网络资源,通常只要给出相对于服务器的根目录的相对目录即可,因此总是以“/”开头,最后,协议版本声明了通信过程中使用HTTP的版本。
(2)请求头(Request Header)
请求头包含许多有关的客户端环境和请求正文的有用信息。例如,请求头可以声明浏览器所用的语言,请求正文的长度等。
(3)请求正文
请求头和请求正文之间是一个空行,这个行非常重要,它表示请求头已经结束,接下来的是请求正文。请求正文中可以包含客户提交的查询字符串信息:
deflate username=jinqiao&password=1234
在以上的例子的HTTP请求中,请求的正文只有一行内容。当然,在实际应用中,HTTP请求正文可以包含更多的内容。
浏览器发送请求的方法
以上代码中“GET”代表请求方法,“/sample.jsp”表示URL,“HTTP/1.1代表协议和协议的版本。根据HTTP标准,HTTP请求可以使用多种请求方法。例如:HTTP1.1支持7种请求方法:GET、POST、HEAD、OPTIONS、PUT(往服务器上面放置一些东西)、DELETE(往服务器上删除一些东西)和TARCE。在Internet应用中,最常用的方法是GET和POST。
GET方法
GET方法是默认的HTTP请求方法,我们日常用GET方法来提交表单数据,然而用GET方法提交的表单数据只经过了简单的编码,同时它将作为URL的一部分向Web服务器发送,因此,如果使用GET方法来提交表单数据就存在着安全隐患上。例如
Http://127.0.0.1/login.jsp?Name=zhangshi&Age=30&Submit=%cc%E+%BD%BB
从上面的URL请求中,很容易就可以辩认出表单提交的内容(?之后的内容)。另外由于GET方法提交的数据是作为URL请求的一部分,所以提交的数据量不能太大。
POST方法
POST方法是GET方法的一个替代方法,它主要是向Web服务器提交表单数据,尤其是大批量的数据。POST方法克服了GET方法的一些缺点。通过POST方法提交表单数据时,数据不是作为URL请求的一部分而是作为标准数据传送给Web服务器,这就克服了GET方法中的信息无法保密和数据量太小的缺点。因此,出于安全的考虑以及对用户隐私的尊重,通常表单提交时采用POST方法。
以下是POST请求的例子。
POST/login/email HTTP/1.1 // 请求行,下面一直到空行之上都是请求头
Host:www.zhihu.com
Accept:*/*
Content-Type: application/x-www-form-urlencoded; charset=UTF-8 // 描述消息体
Content-Length: 119
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9
Cookie: _xsrf=e0f0996099f0c4e3e0157d92d65dfe23;
// 空行
password=zhihu&captcha=mrah&remember_me=true&email=huayiqishi%40qq.com // 消息体
四、服务器的永久重定向响应
服务器给浏览器响应一个301永久重定向响应,这样浏览器就会访问http://www.google.com/而非http://google.com/。
为什么服务器一定要重定向而不是直接发送用户想看的网页内容呢?其中一个原因跟搜索引擎排名有关。如果一个页面有两个地址,就像http://www.yy.com/和http://yy.com/,搜索引擎会认为它们是两个网站,结果造成每个搜索链接都减少从而降低排名。而搜索引擎知道301永久重定向是什么意思,这样就会把访问带 www 的和不带 www 的地址归到同一个网站排名下。还有就是用不同的地址会造成缓存友好性变差,当一个页面有好几个名字时,它可能会在缓存里出现好几次。
301和302的区别
301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)——这是它们的共同点。
他们的不同在于:
301表示 旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;
302表示 旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。 SEO 302好于301
重定向原因:
(1)网站调整(如改变网页目录结构);
(2)网页被移到一个新地址;
(3)网页扩展名改变(如应用需要把.php改成.Html或.shtml)。
这种情况下,如果不做重定向,则用户收藏夹或搜索引擎数据库中旧地址只能让访问客户得到一个404页面错误信息,访问流量白白丧失;再者某些注册了多个域名的网站,也需要通过重定向让访问这些域名的用户自动跳转到主站点等。
什么时候进行301或者302跳转呢?
当一个网站或者网页24—48小时内临时移动到一个新的位置,这时候就要进行302跳转。
使用301跳转的场景就是之前的网站因为某种原因需要移除掉,然后要到新的地址访问,是永久性的。
清晰明确而言,使用301跳转的大概场景如下:
域名到期不想续费(或者发现了更适合网站的域名),想换个域名。
在搜索引擎的搜索结果中出现了不带www的域名,而带www的域名却没有收录,这个时候可以用301重定向来告诉搜索引擎我们目标的域名是哪一个。
空间服务器不稳定,换空间的时候。
浏览器跟踪重定向地址
当浏览器知道了 “http://www.google.com/“才是要访问的正确地址,所以它会发送另一个HTTP请求。
五、服务器处理请求
服务器是一台安装系统的机器,常见的系统如Linux、windows server 2012。系统里安装的处理请求的应用叫 Web server。
常见的 Web server 有 Apache、Nginx、IIS、Lighttpd等。
Web server 接收用户的Request 交给网站代码,或者接受请求反向代理到其他 Web server。
网站处理阶段
网站处理,就是实际后台处理的工作。后台开发现在有很多框架,但大部分都还是按照MVC设计模式进行搭建的。
MVC是一个设计模式,将应用程序分成三个核心部件:模型(model)-- 视图(view)--控制器(controller),它们各自处理自己的任务,实现输入、处理和输出的分离。
1、视图(view)
视图是用户看到并与之交互的界面。这是前端工作的主力部分。
2、模型(model)
模型是将实际开发中的业务规则和所涉及的数据格式模型化,应用于模型的代码只需写一次就可以被多个视图重用。在MVC的三个部件中,模型拥有最多的处理任务。一个模型能为多个视图提供数据。
3、控制器(controller)
控制器接受用户的输入并调用模型和视图去完成用户的需求。Controller处于管理角色,从视图接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示模型处理返回的数据。
总结而言,首先控制器接收用户的请求,并决定应该调用哪个模型来进行处理,然后模型用业务逻辑来处理用户的请求并返回数据,最后控制器用相应的视图格式化模型返回html字符串给浏览器,浏览器呈现网页给用户。
六、服务器返回一个HTML响应
HTTP应答
在接收和解释请求消息后,服务器会返回一个 HTTP 响应消息。与 HTTP 请求类似,HTTP 响应也是由三个部分组成,分别是:状态行、消息报头和响应正文。
1. 协议状态版本代码描述 - HTTP响应的第一行,类似于HTTP请求的第一行,它表示通信所用的协议是HTTP1.1服务器已经成功的处理了客户端发出的请求。(例如状态码200表示成功)
2. 响应头(Response Header) - 响应头也和请求头一样包含许多有用的信息,例如服务器类型、日期时间、内容类型和长度等。由关键字/值对组成,每行一对,关键字和值用英文冒号":"分隔,典型的响应头有:
3. 响应正文 - 包含着我们需要的一些具体信息,比如cookie,html,image,后端返回的请求数据等等。这里需要注意,响应正文和响应头之间有一行空格,表示响应头的信息到空格为止,下图是fiddler抓到的请求正文,红色框中的是响应正文:
下面是一个HTTP响应的例子:
HTTP/1.1 200 OK
Date: Sun, 17 Mar 2013 08:12:54 GMT
Server: Apache/2.2.8 (Win32) PHP/5.2.5
X-Powered-By: PHP/5.2.5
Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache
Content-Length: 4393
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=utf-8
<html>
<head>
<title>HTTP响应实例<title/>
<head/>
<body>
Hello HTTP!
<body/>
<html/>
HTTP应答码
HTTP应答码也称为状态码,它反映了Web服务器处理HTTP请求状态。HTTP应答码由3位数字构成,其中首位数字定义了应答码的类型:
1xx:指示信息——表示请求已经接受,继续处理
2xx:成功——表示请求已经被成功接收、理解、接受。
3xx:重定向——要完成请求必须进行更进一步的操作
4xx:客户端错误——请求有语法错误或请求无法实现
5xx:服务器端错误——服务器未能实现合法的请求。
常见状态代码、状态描述、说明:
200 OK //客户端请求成功
400 Bad Request //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
403 Forbidden //服务器收到请求,但是拒绝提供服务
404 Not Found //请求资源不存在,eg:输入了错误的URL
500 Internal Server Error //服务器发生不可预期的错误
503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常
对于我们Web开发人员来说掌握HTTP应答码有助于提高Web应用程序调试的效率和准确性。
有兴趣了解可以参考 HTTP深入浅出HTTP请求 以及 HTTP-请求、响应、缓存
七、浏览器显示HTML
渲染页面
浏览器下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染同时进行
解析 HTML 生成 DOM 树
解析 HTML 中的 CSS,生成渲染树
解析 JavaScript,解析到的时候执行
浏览器是如何把页面呈现在屏幕上的呢?不同浏览器可能解析的过程不太一样,这里我们只介绍webkit的渲染过程,下图对应的就是WebKit渲染的过程,这个过程包括:
解析html以构建dom树 -> 构建render树 -> 布局render树 -> 绘制render树
浏览器在解析html文件时,会”自上而下“加载,并在加载过程中进行解析渲染。在解析过程中,如果遇到请求外部资源时,如图片、外链的 CSS、iconfont 等,请求过程是异步的,并不会影响 html 文档进行加载。
解析过程中,浏览器首先会解析 HTML 文件构建 DOM 树,然后解析 CSS 文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。这个过程比较复杂,涉及到两个概念: reflow(回流)和 repain(重绘)。
DOM 节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为 relow,当盒模型的位置,大小以及其他属性,如颜色、字体等确定下来之后,浏览器便开始绘制内容,这个过程称为 repain。
页面在首次加载时必然会经历 reflow 和 repain。reflow 和 repain 过程是非常消耗性能的,尤其是在移动设备上,它会破坏用户体验,有时会造成页面卡顿。所以我们应该尽可能少的减少 reflow 和 repain。
当文档加载过程中遇到 JS 文件,html文档会挂起渲染(加载解析渲染同步)的线程,不仅要等待文档中 JS 文件加载完毕,还要等待解析执行完毕,才可以恢复html文档的渲染线程。
因为JS有可能会修改DOM,最为经典的document.write,这意味着,在JS执行完成前,后续所有资源的下载可能是没有必要的,这是 JS 阻塞后续资源下载的根本原因。
所以我们平时的代码中, JS 是放在html文档末尾的。JS的解析是由浏览器中的JS解析引擎完成的,比如谷歌的是V8。
JS是单线程运行,也就是说,在同一个时间内只能做一件事,所有的任务都需要排队,前一个任务结束,后一个任务才能开始。但是又存在某些任务比较耗时,如IO读写等,所以需要一种机制可以先执行排在后面的任务,这就是:同步任务(synchronous)和异步任务(asynchronous)。
JS的执行机制就可以看做是一个主线程加上一个任务队列(task queue)。同步任务就是放在主线程上执行的任务,异步任务是放在任务队列中的任务。所有的同步任务在主线程上执行,形成一个执行栈;异步任务有了运行结果就会在任务队列中放置一个事件;脚本运行时先依次运行执行栈,然后会从任务队列里提取事件,运行任务队列中的任务,这个过程是不断重复的,所以又叫做事件循环(Event loop)。
有兴趣了解更多请参考 浏览器的渲染原理简介
浏览器发送请求获取嵌入在 HTML 中的资源(如图片、音频、视频、CSS、JS等等)
在浏览器显示HTML时,它会注意到需要获取其他地址内容的标签。 例如解析到 link 标签后重新发送请求获取 CSS样式表。
这时,浏览器会发送一个获取请求来重新获得这些文件。比如我要获取外图片,CSS,JS文件等,类似于下面的链接:
图片:http://static.ak.fbcdn.net/rsrc.php/z12E0/hash/8q2anwu7.gif
CSS式样表:http://static.ak.fbcdn.net/rsrc.php/z448Z/hash/2plh8s4n.css
JavaScript 文件:http://static.ak.fbcdn.net/rsrc.php/zEMOA/hash/c8yzb6ub.js
这些地址都要经历一个和HTML请求类似的过程。所以浏览器会在DNS中查找这些域名,发送请求,重定向等等...
不像动态页面,静态文件会允许浏览器对其进行缓存。有的文件可能会不需要与服务器通讯,而从缓存中直接读取,或者可以放到CDN中。
如果直接使用本地缓存,服务器发给浏览器的文件中会带有 Expires 或 Cache-Control 说明文件什么时候失效,在有效期内浏览器直接使用本地文件,不发送请求。
服务器响应中会带有文件的最后修改时间或 Etag,浏览器发送重复请求会带上这些信息。如果服务器判断没有变化,发送304状态码,让浏览器使用本地缓存。
本文暂时整理至此。