地址栏回车后发生了什么

本篇讲述地址栏回车猴发生的事件的讲述

输入地址

当我们开始在浏览器中输入网址的时候,浏览器其实就已经在智能的匹配可能得 url 了,他会从历史记录,书签等地方,找到已经输入的字符串可能对应的 url,然后给出智能提示,让你可以补全url地址。对于 google的chrome 的浏览器,他甚至会直接从缓存中把网页展示出来,就是说,你还没有按下 enter,页面就出来了

浏览器查找域名的 IP 地址 

  1. 请求一旦发起,浏览器首先要做的事情就是解析这个域名,一般来说,浏览器会首先查看本地硬盘的 hosts 文件,看看其中有没有和这个域名对应的规则,如果有的话就直接使用 hosts 文件里面的 ip 地址。

  2. 如果在本地的 hosts 文件没有能够找到对应的 ip 地址,浏览器会发出一个 DNS请求到本地DNS服务器 。本地DNS服务器一般都是你的网络接入服务器商提供,比如中国电信,中国移动。

  3. 查询你输入的网址的DNS请求到达本地DNS服务器之后,本地DNS服务器会首先查询它的缓存记录,如果缓存中有此条记录,就可以直接返回结果,此过程是递归的方式进行查询。如果没有,本地DNS服务器还要向DNS根服务器进行查询。

  4. 根DNS服务器没有记录具体的域名和IP地址的对应关系,而是告诉本地DNS服务器,你可以到域服务器上去继续查询,并给出域服务器的地址。这种过程是迭代的过程。

  5. 本地DNS服务器继续向域服务器发出请求,在这个例子中,请求的对象是.com域服务器。.com域服务器收到请求之后,也不会直接返回域名和IP地址的对应关系,而是告诉本地DNS服务器,你的域名的解析服务器的地址。

  6. 最后,本地DNS服务器向域名的解析服务器发出请求,这时就能收到一个域名和IP地址对应关系,本地DNS服务器不仅要把IP地址返回给用户电脑,还要把这个对应关系保存在缓存中,以备下次别的用户查询时,可以直接返回结果,加快网络访问。

浏览器向 web 服务器发送一个 HTTP 请求

拿到域名对应的IP地址之后,浏览器会以一个随机端口(1024<端口<65535)向服务器的WEB程序(常用的有httpd,nginx等)80端口发起TCP的连接请求。这个连接请求到达服务器端后(这中间通过各种路由设备,局域网内除外),进入到网卡,然后是进入到内核的TCP/IP协议栈(用于识别该连接请求,解封包,一层一层的剥开),还有可能要经过Netfilter防火墙(属于内核的模块)的过滤,最终到达WEB程序,最终建立了TCP/IP的连接.
建立了TCP连接之后,发起一个http请求。一个典型的 http request header 一般需要包括请求的方法,例如 GET 或者 POST 等,不常用的还有 PUT 和 DELETE 、HEAD、OPTION以及 TRACE 方法,一般的浏览器只能发起 GET 或者 POST 请求

客户端向服务器发起http请求的时候,会有一些请求信息,请求信息包含三个部分:

  1. 请求方法URI协议/版本
  2. 请求头(Request Header)
  3. 请求正文:
    下面是一个完整的HTTP请求例子:
    1
    2
    GET/sample.jsp
    HTTP/1.1 Accept:image/gif.image/jpeg,*/*

服务器的永久重定向响应

服务器给浏览器响应一个301永久重定向响应,这样浏览器就会访问“http://www.google.com/” 而非“http://google.com/”。
为什么服务器一定要重定向而不是直接发送用户想看的网页内容呢?其中一个原因跟搜索引擎排名有关。如果一个页面有两个地址,就像http://www.yy.com/和http://yy.com/,搜索引擎会认为它们是两个网站,结果造成每个搜索链接都减少从而降低排名。而搜索引擎知道301永久重定向是什么意思,这样就会把访问带www的和不带www的地址归到同一个网站排名下。还有就是用不同的地址会造成缓存友好性变差,当一个页面有好几个名字时,它可能会在缓存里出现好几次。

浏览器跟踪重定向地址

现在浏览器知道了 “http://www.google.com/"才是要访问的正确地址,所以它会发送另一个http请求。这里没有啥好说的

服务器处理请求

经过前面的重重步骤,我们终于将我们的http请求发送到了服务器这里,其实前面的重定向已经是到达服务器了,那么,服务器是如何处理我们的请求的呢?
后端从在固定的端口接收到TCP报文开始,它会对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用。

服务器返回一个 HTTP 响应

经过前面的6个步骤,服务器收到了我们的请求,也处理我们的请求,到这一步,它会把它的处理结果返回,也就是返回一个HTPP响应。

HTTP响应与HTTP请求相似,HTTP响应也由3个部分构成,分别是:

  1. 状态行
  2. 响应头(Response Header)
  3. 响应正文
1
2
3
4
5
6
7
8
9
10
11
HTTP/1.1 200 OK
Date: Sat, 31 Dec 2005 23:59:59 GMT
Content-Type: text/html;charset=ISO-8859-1 Content-Length: 122
<html>
<head>
<title>http</title>
</head>
<body>
<!-- body goes here -->
</body>
</html>

状态行

状态行由协议版本、数字形式的状态代码、及相应的状态描述,各元素之间以空格分隔。

格式: HTTP-Version Status-Code Reason-Phrase CRLF

例如: HTTP/1.1 200 OK \r\n

协议版本

是用http1.0还是其他版本

状态描述

状态描述给出了关于状态代码的简短的文字描述。比如状态代码为200时的描述为 ok

状态代码

状态代码由三位数字组成,第一个数字定义了响应的类别,且有五种可能取值。如下
1xx:信息性状态码,表示服务器已接收了客户端请求,客户端可继续发送请求。

1
100 Continue 101 Switching Protocols

2xx:成功状态码,表示服务器已成功接收到请求并进行处理。200 OK 表示客户端请求成功

1
2
204 No Content 成功,但不返回任何实体的主体部分
206 Partial Content 成功执行了一个范围(Range)请求

3xx:重定向状态码,表示服务器要求客户端重定向。

1
2
3
4
5
6
301 Moved Permanently 永久性重定向,响应报文的Location首部应该有该资源的新URL
302 Found 临时性重定向,响应报文的Location首部给出的URL用来临时定位资源
303 See Other 请求的资源存在着另一个URI,客户端应使用GET方法定向获取请求的资源
304 Not Modified 服务器内容没有更新,可以直接读取浏览器缓存
307 Temporary Redirect 临时重定向。与302 Found含义一样。
302禁止POST变换为GET,但实际使用时并不一定,307则更多浏览器可能会遵循这一标准,但也依赖于浏览器具体实现

4xx:客户端错误状态码,表示客户端的请求有非法内容。

1
2
3
4
400 Bad Request 表示客户端请求有语法错误,不能被服务器所理解
401 Unauthonzed 表示请求未经授权,该状态代码必须与 WWW-Authenticate 报头域一起使用
403 Forbidden 表示服务器收到请求,但是拒绝提供服务,通常会在响应正文中给出不提供服务的原因
404 Not Found 请求的资源不存在,例如,输入了错误的URL

5xx:服务器错误状态码,表示服务器未能正常处理客户端的请求而出现意外错误。

1
2
500 Internel Server Error 表示服务器发生不可预期的错误,导致无法完成客户端的请求
503 Service Unavailable 表示服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常

响应头

响应头部:由关键字/值对组成,每行一对,关键字和值用英文冒号”:”分隔,

响应正文

包含着我们需要的一些具体信息,比如cookie,html,image,后端返回的请求数据等等。这里需要注意,响应正文和响应头之间有一行空格,表示响应头的信息到空格为止,下图是fiddler抓到的请求正文,红色框中的:响应正文:

浏览器显示 HTML

浏览器在解析html文件时,会”自上而下“加载,并在加载过程中进行解析渲染。在解析过程中,如果遇到请求外部资源时,如图片、外链的CSS、iconfont等,请求过程是异步的,并不会影响html文档进行加载。

浏览器发送请求获取嵌入在 HTML 中的资源(如图片、音频、视频、CSS、JS等等)

其实这个步骤可以并列在步骤8中,在浏览器显示HTML时,它会注意到需要获取其他地址内容的标签。这时,浏览器会发送一个获取请求来重新获得这些文件。比如我要获取外图片,CSS,JS文件等,类似于下面的链接:

1
2
3
图片: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中

总结

从输入url到页面展示的过程全部整理完成。
参考文献:
http://igoro.com/archive/what-really-happens-when-you-navigate-to-a-url/
http://zrj.me/archives/589
https://segmentfault.com/a/1190000006879700

本文总阅读量

坚持原创技术分享,您的支持将鼓励我继续创作!