从输入URL回车后发生的事情

从输入URL 回车后发生的事情

整体过程

  1. DNS域名解析
  2. TCP连接
  3. HTTP请求
  4. 处理请求返回HTTP响应
  5. 页面渲染
  6. 关闭连接

详细过程

DNS(Domain Name System)域名系统

ISP(Internet Service Provider)网络服务提供商

URL(Uniform Resource Locator)统一资源定位符

一. 浏览器查找域名的IP地址

IP地址查找过程如下

  • 浏览器缓存

浏览器会缓存URL记录一段时间。

操作系统没有告诉浏览器储存URL记录的时间

这样不同浏览器会储存各自固定的一个时间(2分钟到30分钟不等)。如果有,就直接向该URL对应的服务器发送请求;如果没有则进行下一步。

  • 系统缓存

如果在浏览器缓存里没有找到需要的记录,浏览器会做一个系统调用(windows里是gethostbyname)。这样便可获得系统缓存中的记录(hosts地址)。如果有,就直接向该URL对应的服务器发送请求;如果没有则进行下一步。

  • 路由器缓存

接着,前面的查询请求发给路由器,它一般会有自己的URL记录缓存。如果没有则进行下一步。

  • ISP DNS缓存

向本地DNS服务器(一般由本地网络接入服务器提供商提供,比如移动)发送DNS请求,本地DNS服务器会首先查询它的缓存记录,如果有,就直接向该URL对应的服务器发送请求,如果没有则进行下一步。

  • 递归搜索

你的ISP的DNS服务器从根域名服务器开始进行递归搜索

首先向根域名服务器发送DNS查询请求,根域名服务器返回给可能保存了该域名的一级域名服务器地址;本地主机再根据返回的地址,向一级域名服务器发送DNS查询请求;…一直迭代,直到找到对应的域名存放的服务器,向其发送DNS查询请求,该域名服务器返回该域名对应的IP地址。

二. TCP/IP 连接

浏览器通过DNS获取到web服务器真的IP地址后,便向web服务器发起tcp连接请求,通过TCP三次握手建立好连接后,浏览器便可以将HTTP请求数据通过发送给服务器了。

刚开始客户端处于 Closed 的状态,服务端处于 Listen 状态。 然后:

  • 第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN(c)。此时客户端处于 SYN_Send 状态。
  • 第二次握手:服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,并且也是指定了自己的初始化序列号 ISN(s)。同时会把客户端的 ISN + 1 作为 ACK 的值,表示自己已经收到了客户端的 SYN,此时服务器处于 SYN_REVD 的状态。
  • 第三次握手:客户端收到 SYN 报文之后,会发送一个 ACK 报文,当然,也是一样把服务器的 ISN + 1 作为 ACK 的值,表示已经收到了服务端的 SYN 报文,此时客户端处于 establised 状态。
  • 服务器收到 ACK 报文之后,也处于 establised 状态,此时,双方已建立起了链接。

三次握手的作用

  • 确认双方的接受能力、发送能力是否正常。
  • 指定自己的初始化序列号,为后面的可靠传送做准备。
  • 如果是 HTTPS 协议的话,三次握手这个过程,还会进行数字证书的验证以及加密密钥的生成。

其他问题:

  1. (ISN)是固定的吗?

三次握手的一个重要功能是客户端和服务端交换 ISN(Initial Sequence Number),以便让对方知道接下来接收数据的时候如何按序列号组装数据。 如果 ISN 是固定的,攻击者很容易猜出后续的确认号,因此 ISN 是动态生成的。

  1. 什么是半连接队列?

服务器第一次收到客户端的 SYN 之后,就会处于 SYN_RCVD 状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。

当然还有一个全连接队列,就是已经完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象。

这里在补充一点关于SYN-ACK 重传次数的问题:

  • 服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传。
  • 如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。

注意,每次重传等待的时间不一定相同,一般会是指数增长,例如间隔时间为 1s,2s,4s,8s……

  1. 三次握手过程中可以携带数据吗?

很多人可能会认为三次握手都不能携带数据,其实第三次握手的时候,是可以携带数据的。

也就是说,第一次、第二次握手不可以携带数据,而第三次握手是可以携带数据的。

为什么这样呢?大家可以想一个问题,假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据。

因为攻击者根本就不理服务器的接收、发送能力是否正常,然后疯狂着重复发 SYN 报文的话,这会让服务器花费很多时间、内存空间来接收这些报文。 也就是说,第一次握手可以放数据的话,其中一个简单的原因就是会让服务器更加容易受到攻击了。

而对于第三次的话,此时客户端已经处于 established 状态,也就是说,对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据页没啥毛病。关于三次

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

处理HTTP请求并响应

服务器在收到浏览器发送的HTTP请求之后,会将收到的HTTP报文封装成HTTP的Request对象,比如Servlet会把请求封装成httpservletrequest对象,把响应封装成httpsevletresponse对象。并通过Web服务器进行处理,处理完的结果以HTTP的Response对象返回。

主要包括状态码,响应头,响应报文三个部分。

状态码主要包括以下部分

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

2xx:成功–表示请求已被成功接收、理解、接受。

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

4xx:客户端错误–请求有语法错误或请求无法实现。

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

响应头主要由Cache-Control、 Connection、Date、Pragma等组成

四. 浏览器渲染

浏览器接收到服务器传来的响应对象,从中得到html字符串和MIME,根据MIME知道了要用页面渲染引擎来处理内容即html字符串,于是进入页面渲染阶段,这又是一个很庞杂的体系。我只能大体上说一下:

从浏览器的角度讲,它包含几大组件,网络功能(比如http的实现)算是其中之一,渲染引擎也是其中之一,还有其它的一些比如自己UI界面,javascript解释器,客户端数据存储等等。在这里我们主要关注渲染引擎和javascript解释器,对于web开发者来说,这才是浏览器的核心。 我们能够在浏览器中看到一个页面,那么这个页面是怎么出现的呢?实际上就是调用底层绘图API给画出来的。不同的渲染引擎,它的实现也不同,主流的引擎包括IE的Trident,chrome和safary的webkit,firefox的Gecko,chrome又出了一个Blink,放弃webkit。于是乎才有了让人头疼的各种兼容性问题。

整体上页面渲染的过程大致是这样的:

渲染引擎得到html字符串作为输入,然后对html进行转换,转化成能够被DOM处理的形式,接着转换成一个dom树,在解析html的过程,解析到,