今日份的学习(1)

打开一个网站的完整过程

描述从URL输入到页面展示的过程发生了什么

  • 在浏览器的地址栏输入URL并按下回车

  • 浏览器拿着URL查找是否有缓存,并且验证缓存是否过期

  • DNS解析对应URL的IP地址

  • 根据IP建立TCP连接(三次握手)

  • 发起HTTP请求

  • 服务器处理请求,浏览器接收HTTP响应

  • 渲染页面,构建DOM树

  • 关闭TCP连接(四次挥手)

URL

用常见的http://www.badu.com为例子。这个域名由三个部分组成:协议域名端口。除此之外URL还会包含其他路径、查询、参数等其他片段。例如:http://www.tuicool.com/search?kw=%E4%。案例中没有体现出域名是因为http协议默认的端口是80,https默认的端口是443。而https是一种加密协议,加密协议还有类似FTP协议、FILE协议等等。

浏览器缓存

http缓存有多种规则,按照是否会重新发起请求,可以归为两类。一类是强制缓存,一类是对比缓存。

  • 强制缓存(判断http首部的两个字段) :cache-control、expires(较少使用)

    • expires:这个是一个绝对时间,即服务器时间。浏览器会检查本地时间,如果时间在有效期内就会直接去拉缓存,如果过了就会重新去请求。但是有一个很大的问题就是,服务器的时间和浏览器可能不一致,所以很少使用这个字段。

    • cache-control:这个字段会在max-age中保存一个相对时间。例如max-age:422555,表示在接受到文件后422555秒内有效。如果同时存在cache-control和expires浏览器总是会优先使用cache-control。

  • 对比缓存:last-modified、etag

    • last-modified:这是第一次请求资源时,服务器返回的字段。在下一次请求的时候,浏览器会带上if-modified-since这个字段,服务器拿到这个字段值去check服务器本地last-modified的时间,如果不一致,就会任务缓存已经过期,然后返回最新的资源给浏览器。

    • etag:资源的实体标识(哈希字符串),当资源内容更新时,Etag会改变。服务器会根据Etag是否发生变化,如果变化则会返回新资源,否则返回304

DNS域名解析

因为资源所在的位置有对应的一个IP地址,而网络服务器的IP地址众多,所以采用了域名和IP的映射关系,这样更容易被记住。而域名解析就是找到域名对应映射的IP的地址的过程。

  • 首先浏览器先检查本地hosts文件是否有这个网址映射的关系,如果有就直接调用这个IP,完成域名解析

  • 如果没有找到则会查找本地DNS解析器缓存,如果查到就返回

  • 如果还是没找到,就会找本地DNS服务器,如果找到则返回

  • 最后迭代查询

TCP连接

通过DNS域名解析之后,获取到了服务器IP地址,获取到IP地址之后,便会开始建立一次连接,这是由TCP协议完成的,主要通过三次握手进行连接。

  • 第一次握手:建立连接时,客户端发送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连接成功)状态,完成三次握手

  • 完成三次握手,客户端与服务器开始传送数据

浏览器向服务器发送HTTP请求

完整的HTTP请求包含请求起始行 请求头 请求主体三个部分

浏览器接收响应

服务器在收到浏览器发送的HTTP请求之后,会将收到的HTTP的request对象,并通过不同的web服务器进行处理,处理完的结果以HTTP的response对象返回,主要包括状态码 响应头 响应报文三个部分

关于状态码:

1xx:指示信息,表示请求已接收,继续处理

2xx:请求已被成功接收、理解、接受

3xx:重定向,要完成请求必须进行更进一步的操作

4xx:客户端错误,请求语法错误或是请求无法实现

5xx:服务器端错误,服务器未能实现合法的请求

响应头主要有cache-control connection date pragma等组成
响应体主要是服务器返回给浏览器的信息,主要有html css js 图片文件等组成

页面渲染

如果响应的内容是HTML文档的话,就需要浏览器进行解析渲染呈现给用户。整个过程涉及两个方面:解析和渲染。在渲染之前需要构建DOM树和CSSOM树。

在浏览器还没接收到完整的HTML文件的时,他就开始渲染页面了,在遇到外部链入的脚本标签或样式或图片时,会再次发起http请求重复上面的步骤。在收到css文件后会对已经渲染的页面重新渲染,加入他们应有的样式,图片文件加载完立刻显示在相应位置。在这一过程中可能会触发页面的重绘或重排。这里就涉及到reflowrepaint两个重要的概念了。

  • reflow:也称作layout,中文叫回流,一般意味着元素的内容、结构、位置或尺寸发生了变化,需要重新计算样式和渲染树,这个过程称为reflow

  • repaint:中文重绘,意味着元素发生的改变只影响了元素的一些外观之类的时候(背景色、边框颜色、文字颜色等),此时只需要重绘这个元素就可以了,这个过程称为repaint

所以说reflow的成本比repaint高的多的多。DOM树里的每个节点都有reflow方法,一个节点的reflow很有可能导致子节点,甚至父节点以及同级节点的reflow

下面的这些动作,有很大可能会造成较高的成本:

  • 增加、删除、修改DOM节点时,会导致回流或重绘

  • 移动DOM的位置,或是搞一个动画

  • 内容发生变化

  • 修改CSS样式

  • resize窗口(移动端没有这个问题)

  • 滚动

  • 修改网页默认字体

关闭TCP连接或继续保持连接

通过四次挥手关闭连接

  • 第一次挥手是浏览器发完数据后,发送FIN请求断开连接

  • 第二次挥手是服务器收到这个FIN发送ACK表示同意,确认序号为收到的序号+1

  • 第三次挥手是服务器关闭与客户端的连接并发送一个FIN给客户端

  • 第四次挥手是客户端发回ACK报文确认,将确认序号设置为收到的序号+1

为什么要三次握手却要四次挥手呢

是因为服务器端listen状态下的socket当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,但收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了,但未必你所有的数据都给对方了,所以你未必马上会关闭socket,你可能还有一些数据要发送给对方之后,再发送FIN报文表示你同意现在可以关闭连接了。所以,他这里ACK报文和FIN报文多数情况下是分开发送。

死锁产生的原因和解锁的方法

产生死锁的四个必要条件

  • 互斥条件:进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其他进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放

  • 请求和保持条件:进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放

  • 不剥夺条件:进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放

  • 环路等待条件:在发生死锁时,必然存在一个进程—资源的环形链,即进程集合{P0,P1,P2,…,Pn}中的P0正在等待一个P1占用的资源;P1等待P2占用的资源…Pn等待P0占用的资源

锁的原理

  • 死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所占用不会释放的资源而处于一种永久等待的状态