1.输入地址
这个时候浏览器会从历史记录,书签等地方找到 缓存 的url自动帮用户补全,给出智能提示。然后用户按下 enter键。
2.浏览器解析url获取到协议,主机,端口号,path
1.当请求发起的时候,浏览器开始解析这个域名。一般来说,浏览器会先去本地host中找于域名是否被代理,有的话解析出来的就是对应规则的ip地址;
# For example:
# 102.54.94.97 www.baidu.com
2.如果在本地的host中没有找到对应的规则,浏览器就会发起一个DNS请求到本地DNS服务器,本地DNS服务器一般都是用户的网络接入服务器商提供,比如中国电信,中国移动。
3.本地DNS服务器开始查询用户输入的网址的缓存记录(参考2-6),如果缓存中有记录,就直接返回结果,这个过程是递归的查询过程,如果本地DNS服务器发现没有缓存记录,则向DNS根服务器进行查询;
4.根DNS服务器没有记录具体域名和ip的对应关系,而是告诉本地的DNS服务器,你可以去域服务器上继续查询,并给出域服务器的地址,这个过程是迭代的过程。
5.本地DNS服务器继续向域服务器发出请求,域服务器收到请求后,不会直接返回域名和ip的对应关系,而是告诉本地DNS服务器,输入的域名的解析服务器的地址;
6.本地DNS服务器收到解析服务器地址,并向解析服务器地址发出请求,并返回一个域名和ip地址的对应关系,本地DNS服务器不仅要把地址返回浏览器,还要把这个关系缓存起来,下次再访问这个域名的时候,就可以直接返回结果了,加速网络的访问。
3.浏览器组装一个HTTP (GET) 请求报文
拿到域名对应的ip地址后,浏览器就会以一个随机端口(1024 < x < 65535)向服务器的80端口发送TCP请求连接。这个链接进入服务器端后,进入网卡,进入内核的TCP/IP协议栈(可能还有防火墙),最终到达服务器端的web程序,并成功建立TCP/IP连接。
TCP建立后,发起一个http请求,一个典型的 http request header 一般需要包括请求的方法,例如 GET 或者 POST 等,不常用的还有 PUT 和 DELETE 、HEAD、OPTION以及 TRACE 方法,一般的浏览器只能发起 GET 或者 POST 请求。
客户端向服务器端发送的请求包括哪些内容?
1.请求方法/URL协议/版本
2.请求头(Request header)
3.请求正文
GET/sample.jspHTTP/1.1 // 方法URL议/版本
// Request Header start
// 请求头包含许多有关的客户端环境和请求正文的有用信息。
// 例如,请求头可以声明浏览器所用的语言,请求正文的长度等。
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
// Request Header end
// 请求正文
// 请求头和请求正文之间是一个空行,这个行非常重要,它表示请求头已经结束,接下来的是请求正文。
// 请求正文中可以包含客户提交的查询字符串信息:
username=jinqiao&password=1234
TCP三次握手:
第一次握手:客户端发送一个SYN= 1(标志位, 1代表要建立连接),seq=x(x为随机数)的数据包到服务器,然后客户端进入SYN_SENT状态,等待服务器端的确认;
第二次握手:服务器端收到客户端标志位SYN=1的请求包知道客户端想要建立连接,服务器端将SYN和ACK都设置成1,ack=x + 1,随机生成一个seq=y,并将数据包返回给客户端以确认连接请求,服务器端进入SYN_RCVD状态;
第三次握手:客户端收到数据包后,先判断ack是否为x+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=y+1,并将数据包再发给服务器端,服务器端检查ack=y+1?ACK=1?如果是的话,则连接成功建立。客户端和服务器端都进入ESTABLISHED状态,三次握手完成,客户端和服务器端连接建立,他么可以传输数据了。
TCP四次挥手:
第一次挥手:客户端向服务端发送一个FIN=m请求,用来关闭客户端到服务端的数据传送,此时客户端进入FIN_WAIT_1状态;
第二次挥手:服务器端收到FIN请求后,向客户端发送ack=m+1的数据包,服务器端进入CLOSE_WAIT状态;
第三次挥手:服务器端再发送一个FIN,用来关闭服务器端到客户端的数据传送,此时服务器端进入LAST_ACK状态;
第四次挥手:客户端收到FIN后,进入TIME_WAIT状态,发送一个序号+1的ack,服务器端接收到进入CLOSED状态,完成四次挥手。
4.服务器将响应报文通过连接好的TCP连接发送返回给浏览器,浏览器接收HTTP响应
后端从固定的端口接收到TCP报文开始,就会对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用。(这一层可能会经历反向代理配置),
http响应格式:
1.状态行
2.响应头(Response Header)
3.响应正文
// 状态行由协议版本、数字形式的状态代码、及相应的状态描述,各元素之间以空格分隔。
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>
5. 浏览器显示 HTML
1.解析html文档;
2.构建dom树;
3.构建css树;
4.构建render树;
5.布局render树;
6.绘制render树。
1.浏览器在解析html文件的时候,会“自上而下的”加载,并在加载过程中进行解析和渲染,在解析过程中若需要请求外部资源时,比如图片,外链css,请求过程是异步的,并不会影响html文档进行加载。
2.解析过程中,浏览器首先会解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。这个过程比较复杂,涉及到两个概念: reflow(回流)和repain(重绘)。
3.DOM节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为relow;当盒模型的位置,大小以及其他属性,如颜色,字体,等确定下来之后,浏览器便开始绘制内容,这个过程称为repain。
4.页面在首次加载时必然会经历reflow和repain。reflow和repain过程是非常消耗性能的,尤其是在移动设备上,它会破坏用户体验,有时会造成页面卡顿。所以我们应该尽可能少的减少reflow和repain。
5.当文档加载过程中遇到js文件,html文档会挂起渲染(加载解析渲染同步)的线程,不仅要等待文档中js文件加载完毕,还要等待解析执行完毕,才可以恢复html文档的渲染线程。因为JS有可能会修改DOM,最为经典的document.write,这意味着,在JS执行完成前,后续所有资源的下载可能是没有必要的,这是js阻塞后续资源下载的根本原因。所以我明平时的代码中,js是放在html文档末尾的。
6.JS的解析是由浏览器中的JS解析引擎完成的, JS是单线程运行,也就是说,在同一个时间内只能做一件事,所有的任务都需要排队,前一个任务结束,后一个任务才能开始。但是又存在某些任务比较耗时,如IO读写等,所以需要一种机制可以先执行排在后面的任务,这就是:同步任务(synchronous)和异步任务(asynchronous)。(这里可以引出js的事件循环机制)