一次完整的http请求
一次完整的http请求的过程如下:
1、浏览器的地址栏输入URL并按下回车。
2、DNS解析。
3、根据IP建立TCP连接(三次握手)。
4、HTTP发起请求。
5、服务器处理请求,浏览器接收HTTP响应。
6、浏览器显示 HTML,构建DOM树。
7、关闭TCP连接(四次挥手)。
一,url一般由三部分组成:协议名(http,https)、域名(baidu)、端口号(80),端口号一般是默认隐藏的。
在浏览器中输入url后,首先浏览器查找当前URL是否存在缓存(浏览器缓存),并比较缓存是否过期。如图
浏览器缓存判断流程图
二,dns域名解析
没有缓存或者缓存过期,则进行dns解析,dns解析可以理解为翻电话本的过程,人擅长于记住一些有规律的字母(baidu),计算机更偏爱数字(61.135.169.121),访问百度有两种方式,一种在地址栏输入www.baidu.com,另一种输入61.135.169.121,相信你会更喜欢有规律的字母,所以就需要一个负责转换的服务器, 将对应的域名(baidu)转换成ip地址(61.135.169.121),dns服务器就是负责完成这一转换过程。
下面是在一次的http请求中域名解析过程。
首先浏览器先检查本地hosts文件是否有这个网址映射关系,如果有就调用这个IP地址映射,完成域名解析。
如果没找到则会查找本地DNS解析器缓存,如果查找到则返回。
如果还是没有找到则会查找本地DNS服务器,如果查找到则返回。
最后迭代查询,按根域服务器 ->顶级域,.cn->第二层域,http://hb.cn ->子域,http://www.hb.cn的顺序找到IP地址。
知识拓展:DNS负载均衡
当一个网站有足够多的用户的时候,假如每次请求的资源都位于同一台机器上面,那么这台机器随时可能会蹦掉。处理办法就是用DNS负载均衡技术,它的原理是在DNS服务器中为同一个主机名配置多个IP地址,在应答DNS查询时,DNS服务器对每个查询将以DNS文件中主机记录的IP地址按顺序返回不同的解析结果,将客户端的访问引导到不同的机器上去,使得不同的客户端访问不同的服务器,从而达到负载均衡的目的。例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等。
三,根据IP建立TCP连接(三次握手)
在得到目标服务器的ip地址以后,客户端需要和目标服务器建立连接,建立连接的这一个过程,业内称为'三次握手',具体过程如下。
第一次握手: 建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;
第二次握手: 服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手: 客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据。
如下(盗图)。^_^
三次握手
那么,为什么是需要三次握手呢??
知识拓展:为什需要三次握手?
《计算机网络》第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”
书中的例子是这样的,“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。
假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”。主要目的防止server端一直等待,浪费资源。
四.HTTP发起请求。
完整的HTTP请求包含请求起始行、请求头部、请求主体三部分。如图中对应的三部分
http请求报文
五,服务器处理请求,浏览器接收HTTP响应。
HTTP响应与HTTP请求相似,HTTP响应也由3个部分构成,分别是:状态行,响应头(Response Header),响应正文。其中有一个很重要的信息,状态码(在状态行中)。
知识拓展:状态码
1xx:信息性状态码,表示服务器已接收了客户端请求,客户端可继续发送请求。
100 Continue
101 Switching Protocols
2xx:成功状态码,表示服务器已成功接收到请求并进行处理。
200 OK 表示客户端请求成功
204 No Content 成功,但不返回任何实体的主体部分
206 Partial Content 成功执行了一个范围(Range)请求
3xx:重定向状态码,表示服务器要求客户端重定向。
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:客户端错误状态码,表示客户端的请求有非法内容。
400 Bad Request 表示客户端请求有语法错误,不能被服务器所理解
401 Unauthonzed 表示请求未经授权,该状态代码必须与 WWW-Authenticate 报头域一起使用
403 Forbidden 表示服务器收到请求,但是拒绝提供服务,通常会在响应正文中给出不提供服务的原因
404 Not Found 请求的资源不存在,例如,输入了错误的URL
5xx:服务器错误状态码,表示服务器未能正常处理客户端的请求而出现意外错误。
500 Internel Server Error 表示服务器发生不可预期的错误,导致无法完成客户端的请求
503 Service Unavailable 表示服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常
六,浏览器显示 HTML,构建DOM树。
在浏览器还没接收到完整的 HTML 文件时,它就开始渲染页面了,在遇到外部链入的脚本标签或样式标签或图片时,会再次发送 HTTP 请求重复上述的步骤即浏览器发送请求获取嵌入在 HTML 中的资源(如图片、音频、视频、CSS、JS等等)。在收到 CSS 文件后会对已经渲染的页面重新渲染,加入它们应有的样式,图片文件加载完立刻显示在相应位置。在这一过程中可能会触发页面的重绘或重排。这里就涉及了两个重要概念:Reflow和Repaint。
Reflow,也称作Layout,中文叫回流,一般意味着元素的内容、结构、位置或尺寸发生了变化,需要重新计算样式和渲染树,这个过程称为Reflow。
Repaint,中文重绘,意味着元素发生的改变只是影响了元素的一些外观之类的时候(例如,背景色,边框颜色,文字颜色等),此时只需要应用新样式绘制这个元素就OK了,这个过程称为Repaint。
所以说Reflow的成本比Repaint的成本高得多的多。DOM树里的每个结点都会有reflow方法,一个结点的reflow很有可能导致子结点,甚至父点以及同级结点的reflow。
页面渲染过程
知识拓展:
下面这些动作有很大可能会是成本比较高的:
增加、删除、修改DOM结点时,会导致Reflow或Repaint
移动DOM的位置,或是搞个动画的时候
内容发生变化
修改CSS样式的时候
Resize窗口的时候(移动端没有这个问题),或是滚动的时候
修改网页的默认字体时
基本上来说,reflow有如下的几个原因:
Initial,网页初始化的时候
Incremental,一些js在操作DOM树时
Resize,其些元件的尺寸变了
StyleChange,如果CSS的属性发生变化了
Dirty,几个Incremental的reflow发生在同一个frame的子树上
7,关闭TCP连接(四次挥手)
第一次挥手是浏览器发完数据后,发送FIN请求断开连接。
第二次挥手是服务器发送ACK表示同意,如果在这一次回应中也发送FIN请求断开是不妥的,因为浏览器发送FIN表示浏览器不发送数据了,但是有可能它还需要接受数据,因此,是否断开服务器向浏览器发送数据的这个信息应该由服务器自己来判断,在服务器发送完数据后,再发送FIN,表示不再发送数据,浏览器响应确认,至此,连接断开。之前在建立连接时三次握手中将服务器返回浏览器的确认信息和请求连接的信息是一起发送的,所以,建立连接握手是三次,而断开是四次。(完)
参考:
https://blog.csdn.net/lbxoqy/article/details/71514998
https://zhuanlan.zhihu.com/p/81267752?utm_source=wechat_session