浏览器输入url地址到显示主页的过程
不得不说这是面试里的一位常客,咱们能够把这整个构成分红DNS解析、TCP链接、发送HTTP请求、服务器处理请求并返回HTTP报文、浏览器解析渲染页面、链接结束这六个阶段,接下来详细讲解一下这几个阶段:
其实开始以前,还有几个过程:那就是浏览器要对用户输入的网址作初步的格式化检查(好比baidu@.com1是非法无效的),只有经过了这一步才会继续,还有就是浏览器会首先查询自身缓存,若是有的话直接返回,没有的话继续下面的过程:css
DNS解析
拿百度为例,当你输入www.baidu.com的时候,计算机并不知道它在哪,而是须要知道ip地址才能够进行请求,也就是说,咱们要作的第一步就是如何经过url地址来得到目的ip地址。
那有些人就有疑问了:既然这么麻烦,那为何咱们要使用域名而不是直接使用ip地址,这是由于:git
- IP地址不容易记住,特定的域名,更加方便用户记忆或辨识
- IP地址与域名并非一对一的映射关系,一个域名能够对应多台设备的IP地址,一个IP地址只能对应一个域名
这里引入一个概念叫作DNS解析,DNS解析就是为了将网址转变为相应的ip地址,其中DNS解析是一个递归查询的过程:github
- 首先,本机先经过DNS服务器在DNS高速缓存和本地硬盘里的host文件查询是否有www.baidu.com的ip地址,若是查到直接将结果返回给计算机,结束。反之,若是没有找到,继续下一步。
这里插一句:访问www.github.com的速度很慢的缘由是github服务器在国外所以会被墙,这个时候能够尝试修改本地host文件在最后加上 域名 + ip地址,这样的话能够缩短访问时间。
- 本地域名服务器继续询问根域名服务器(.),根域名服务器返回对应的顶级域名服务器(com)地址给本地域名服务器返回
- 本地域名服务器根据顶级域名服务器地址访问顶级域名服务器(com),顶级域名服务器将baidu.com的地址返回给本地域名服务器
- 本地域名服务器根据baidu.com域名服务器的地址找到baidu.com域名服务器,询问www.baidu.com的IP,并获得返回结果
- 本地域名服务器将获得的结果返回给本机,同时将获得的地址保存在DNS高速缓存一段时间,避免下次访问还会经历不少步骤。
- 本地域名服务器将获得www.baidu.com的地址给浏览器,同时浏览器会对www.baidu.com进行缓存,方便下次访问。
关于DNS,这里继续讨论一下关于DNS优化的问题:
- DNS缓存,避免DNS解析(涉及到UDP和TCP请求)中进行太多的查找,因此DNS中存在着多级缓存,包括浏览器缓存、系统缓存、路由器缓存、根域名服务器缓存、顶级域名服务器缓存等等
- DNS负载均衡,又叫DNS重定向,咱们知道一个网站背后可能有不少机器,DNS服务器会返回给用户距离他最近的点的IP地址
浏览器拿到DNS服务器传输回来的ip地址以后,会把ip地址打到协议上,同时请求参数也会在协议搭载,而后发给对应的服务器,HTTP请求分红三个阶段:TCP链接、HTTP请求相应信息、TCP断开链接面试
TCP链接
TCP三次握手的过程

最初,Client和Server都处于CLOSED(关闭)状态,本例中Client主动打开链接,Server被动打开。Server的TCP服务器首先建立传输控制块TCB,准备接受客户端进程的链接请求,而后Server就处于LISTEN(监听)状态,等待客户端的链接请求。
第一次(红色表示):Client首先建立传输控制块TCB,再打算创建TCP链接时,向B发出链接请求报文段,客户端给服务器端发送一个SYN = 1(同步序列号)和一个初始seq序列号。不能携带数据
第二次(蓝色标识):服务器端返回SYN/ACK标识符,以及Seq和ack,不能携带数据
第三次(绿色标识):客户端收到Server的确认以后,给Server发送确认信息,这是ACK = 1,Seq = X+1,ack = Y + 1。这是,TCP链接已经创建,Client进入ESTABLISHED(已创建链接)状态。浏览器
为何是三次,不是两次或者四次握手
- 为何不是两次
为了防止已经失效的链接请求报文段忽然又传送到了Server,于是产生错误,咱们假设一种状况:Client发出的第一个链接请求报文段并无丢失,而是在网络结点长时间的滞留了,致使它会在链接释放以后的某个时间到达Server。原本这是一个早已失效的报文段,可是Server收到此报文段后,误觉得Client又发出了一次新的请求,因而就向Client发出确认报文段,赞成建议链接。
若是不采起三次握手,Server发出确认以后就默认为新的链接已经创建了,并一直等待Client发来数据,这会致使浪费Server的不少资源。
假如采用了三次握手,因为Client实际上并无发送创建链接的请求,因此会忽略Server发送来的确认,也不会向Server发送数据,Server因为收不到Client返回的确认信息,知道Client并无要求创建链接
- 为何不是四次
由于经过三次握手,服务端和客户端均可以相互确认对方的通讯情况,都收到了确认信息,因此再次增长握手次数没有太大的意义。
为何要传回SYN
SYN是TCP/IP创建链接的时候的握手信号。客户端首先向服务端发送一个SYN消息,服务器使用SYN-ACK应答表示接收到了这个信号,这之中接收端传回SYN,就是为了告诉发送端,我接收到的信息确实就是你发送的信号。缓存
传了SYN,为何还要传ACK
这是由于双方的要创建链接必需要肯定双方都可以互相发送信息,传输SYN,只能确保客户端可以正确发送消息给服务端,可是接收方 -> 发送方的通道还须要ACK来进行验证。服务器
发送HTTP请求
构建HTTP请求报文,关于HTTP请求我会放到别的文章当中来说。网络
服务器处理请求并返回HTTP报文
服务器接收到这个请求,并根据路径参数映射到特 定的请求处理器进行处理,并将处理结果及相应的视图返回给浏览器,这里我也放到别的文章来说。负载均衡
浏览器解析渲染页面
浏览器解析并渲染视图,若遇到对 js 文件、css 文件及图片等静 态资源的引用,则重复上述步骤并向服务器请求这些资源;浏览器根据其请求到的资源、 数据渲染页面,终向用户呈现一个完整的页面。优化
链接结束
咱们知道,当数据发送完毕以后,须要断开TCP的链接,这涉及到TCP断开链接的四次挥手过程,接下来咱们来关注一下TCP断开链接的四次挥手过程以及过程当中遇到的问题。
TCP断开链接四次挥手过程
- 第一次挥手: A 的应用进程先向其 TCP 发出链接释放报文段,并中止再发送数据,主动关闭 TCP 链接。A 把链接释放报文段首部的终止控制位 FIN 置 1,其序号 seq = u(等于前面已传 送过的数据的后一个字节的序号加 1),这时 A 进入 FIN-WAIT-1(终止等待1)状态,等 待 B 的确认。请注意:TCP 规定,FIN 报文段即便不携带数据,也将消耗掉一个序号。
- 第二次挥手: B 收到链接释放报文段后当即发出确认,确认号是 ack = u + 1,而这个报文段本身 的序号是 v(等于 B 前面已经传送过的数据的后一个字节的序号加1),而后 B 就进入 CLOSE-WAIT(关闭等待)状态。TCP 服务端进程这时应通知高层应用进程,于是从 A 到 B 这个方向的链接就释放了,这时的 TCP 链接处于半关闭(half-close)状态,即 A 已经没 有数据要发送了,但 B 若发送数据,A 仍要接收。也就是说,从 B 到 A 这个方向的链接并 未关闭,这个状态可能会持续一段时间。A 收到来自 B 的确认后,就进入 FIN-WAIT-2(终止等待2)状态,等待 B 发出的链接释放报 文段。
- 第三次挥手: 若 B 已经没有要向 A 发送的数据,其应用进程就通知 TCP 释放链接。这时 B 发出的 链接释放报文段必须使 FIN = 1。假定 B 的序号为 w(在半关闭状态,B 可能又发送了一 些数据)。B 还必须重复上次已发送过的确认号 ack = u + 1。这时 B 就进入 LASTACK(后确认)状态,等待 A 的确认。
- 第四次挥手: A 在收到 B 的链接释放报文后,必须对此发出确认。在确认报文段中把 ACK 置 1,确 认号 ack = w + 1,而本身的序号 seq = u + 1(前面发送的 FIN 报文段要消耗一个序 号)。而后进入 TIME-WAIT(时间等待) 状态。请注意,如今 TCP 链接尚未释放掉。必 须通过时间等待计时器设置的时间 2MSL(MSL:长报文段寿命)后,A 才能进入到 CLOSED 状态,而后撤销传输控制块,结束此次 TCP 链接。固然若是 B 一收到 A 的确认就进入 CLOSED 状态,而后撤销传输控制块。因此在释放链接时,B 结束 TCP 链接的时 间要早于 A。
为何 A 在 TIME-WAIT 状态必须等待 2MSL 的时间呢?
- 为了保证 A 发送的最后一个 ACK 报文段可以到达 B。这个 ACK 报文段有可能丢失, 于是使处在 LAST-ACK 状态的 B 收不到对已发送的 FIN + ACK 报文段的确认。B 会超时 重传这个 FIN+ACK 报文段,而 A 就能在 2MSL 时间内(超时 + 1MSL 传输)收到这个 重传的 FIN+ACK 报文段。接着 A 重传一次确认,从新启动 2MSL 计时器。后,A 和 B 都正常进入到 CLOSED 状态。若是 A 在 TIME-WAIT 状态不等待一段时间,而是在发送完 ACK 报文段后当即释放链接,那么就没法收到 B 重传的 FIN + ACK 报文段,于是也不会 再发送一次确认报文段,这样,B 就没法按照正常步骤进入 CLOSED 状态。
- 防止已失效的链接请求报文段出如今本链接中。A 在发送完后一个 ACK 报文段后, 再通过时间 2MSL,就可使本链接持续的时间内所产生的全部报文段都从网络中消失。 这样就可使下一个链接中不会出现这种旧的链接请求报文段。
为何第二次和第三次不能合并,第二次和第三次之间等待的什么
当服务器执行第二次挥手以后, 此时证实客户端不会再向服务端请求任何数据, 可是服 务端可能还正在给客户端发送数据(多是客户端上一次请求的资源尚未发送完毕), 因此此时服务端会等待把以前未传输完的数据传输完毕以后再发送关闭请求。
保活计时器
除时间等待计时器外,TCP 还有一个保活计时器(keepalive timer)。设想这样的 场景:客户已主动与服务器创建了 TCP 链接。但后来客户端的主机忽然发生故障。显然,服务器之后就不能再收到客户端发来的数据。所以,应当有措施使服务器不要再白白等待下去。这就须要使用保活计时器了。
服务器每收到一次客户的数据,就从新设置保活计时器,时间的设置一般是两个小 时。若两个小时都没有收到客户端的数据,服务端就发送一个探测报文段,之后则每隔 75 秒钟发送一次。若连续发送 10个 探测报文段后仍然无客户端的响应,服务端就认为客户端 出了故障,接着就关闭这个链接。
本文部份内容参考自:
1.https://zhuanlan.zhihu.com/p/...2.《计算机网络-自顶向下方法》