[TOC] **1\. 浏览器输入URL后发生了什么?各个步骤都用到了哪些协议?** **一会说。** **2\. 浏览器在与服务器建立了一个 TCP 连接后是否会在一个 HTTP 请求完成后断开?什么情况下会断开?** ~~~ 默认情况下建立 TCP 连接不会断开,只有在请求报头中声明 Connection: close 才会在请求完成后关闭连接 ~~~ **3\. 一个 TCP 连接可以对应几个 HTTP 请求?(这在问你HTTP1.0和1.1的区别)** ~~~ 了解了上个问题之后,其实这个问题已经有了答案,如果维持连接,一个 TCP 连接是可以发送多个 HTTP 请求的 ~~~ **4\. 为什么有的时候刷新页面不需要重新建立 SSL 连接?** ~~~ TCP 连接有的时候会被浏览器和服务端维持一段时间。TCP 不需要重新建立,SSL 自然也会用之前的 ~~~ **5\. 一个 TCP 连接中 HTTP 请求发送可以一起发送么(比如一起发三个请求,再三个响应一起接收)?(提示,这就是在问你HTTP2.0和HTTP1.1协议的区别)** ~~~ HTTP/1.1 存在一个问题,单个 TCP 连接在同一时刻只能处理一个请求,即:两个请求的生命周期不能重叠,任意两个 HTTP 请求从开始到结束的时间在同一个 TCP 连接里不能重叠。虽然 HTTP/1.1 规范中规定了 Pipelining 来试图解决这个问题,但现代浏览器默认是不开启 HTTP Pipelining 的。HTTP2 提供了 Multiplexing 多路传输特性,可以在一个 TCP 连接中同时完成多个 HTTP 请求 所以问题的答案是:在 HTTP/1.1 存在 Pipelining 技术可以完成这个多个请求同时发送,但是由于浏览器默认关闭,所以可以认为这是不可行的。在 HTTP2 中由于 Multiplexing 特点的存在,多个 HTTP 请求可以在同一个 TCP 连接中并行进行 ~~~ **6\. 浏览器对同一Host建立TCP连接到数量有没有限制?(拜托,一个网站那么多图片,开一个TCP连接,按顺序下载?那不是等到死?)** ~~~ 有。Chrome 最多允许对同一个 Host 建立六个 TCP 连接。不同的浏览器有一些区别 ~~~ **7\. 收到的 HTML 如果包含几十个图片标签,这些图片是以什么方式、什么顺序、建立了多少连接、使用什么协议被下载下来的呢?**  ~~~ 如果图片都是 HTTPS 连接并且在同一个域名下,那么浏览器在 SSL 握手之后会和服务器商量能不能用 HTTP2,如果能的话就使用 Multiplexing 功能在这个连接上进行多路传输。不过也未必会所有挂在这个域名的资源都会使用一个 TCP 连接去获取,但是可以确定的是 Multiplexing 很可能会被用到。 如果发现用不了 HTTP2 呢?或者用不了 HTTPS(现实中的 HTTP2 都是在 HTTPS 上实现的,所以也就是只能使用 HTTP/1.1)。那浏览器就会在一个 HOST 上建立多个 TCP 连接,连接数量的最大限制取决于浏览器设置,这些连接会在空闲的时候被浏览器用来发送新的请求,如果所有的连接都正在发送请求呢?那其他的请求就只能等等了 ~~~ # 1\. 浏览器输入URL后发生了什么? **这个问题可以分为八个步骤,每一部都可以拆开讲**,我先列出来,有空就补~(也可能永远没空)~ 并且,后面都带着连珠炮一样的提问,当时被字节问傻了.. ## 1.1 根据域名,进行DNS解析,拿到IP地址(DNS/HTTP/HTTPS协议,属于应用层协议) * 浏览器搜索自己的**DNS**缓存,缓存中维护一张域名与IP地址的对应表; * 没有则查hosts文件,看是否有对应的映射。 * 若没有,则搜索操作系统的DNS缓存; * 若没有,则操作系统将域名发送至本地域名服务器(递归查询方式),本地域名服务器查询自己的DNS缓存,查找成功则返回结果,否则,通过以下方式迭代查找: * 本地域名服务器向根域名服务器发起请求,根域名服务器返回com域的顶级域名服务器的地址; * 本地域名服务器向com域的顶级域名服务器发起请求,返回权限域名服务器地址; * 本地域名服务器向权限域名服务器发起请求,得到IP地址;![](https://img-blog.csdnimg.cn/20200625162320569.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3VvbmVsZQ==,size_16,color_FFFFFF,t_70) ## 1.2 封装数据,并三次握手建立TCP连接(传输层) ### 1.2.1  应用层:发送 HTTP 请求 在前面的步骤我们已经得到服务器的 IP 地址,浏览器会开始构造一个 HTTP 报文,其中包括: * 请求报头(Request Header):请求方法、目标地址、遵循的协议等等 * 请求主体(其他参数) 其中需要注意的点: * 浏览器只能发送 GET、POST 方法,而打开网页使用的是 GET 方法 ### 1.2.1 传输层:TCP 传输报文 选择传输协议,**TCP或者UDP**,TCP是可靠的传输控制协议,对HTTP请求进行封装,加入了端口号等信息; 对于TCP协议,传输层会发起一条到达服务器的 TCP 连接,为了方便传输,会对数据进行分割(以报文段为单位),并标记编号,方便服务器接受时能够准确地还原报文信息。 在建立连接前,会先进行 TCP 三次握手。 ## 1.3 向IP地址发送HTTP请求(网络层+数据链路层) ### 1.3.1 网络层:IP协议查询Mac地址 通过**IP协议**将**IP地址**封装为**IP数据报,**并加入源及目标的IP地址,并且负责寻找传输路线。 判断目标地址是否与当前地址处于同一网络中,是的话直接根据 Mac 地址发送,否则使用路由表查找下一跳MAC地址,此时会用到**ARP协议**,主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址,找到目的MAC地址。 > 注意:在 OSI 参考模型中 ARP 协议位于链路层,但在 TCP/IP 中,它位于网络层 ### **1.3.2 数据链路层:以太网协议** **以太网协议**        接下来到了数据链路层,把网络层交下来的IP数据报添加首部和尾部,封装为MAC帧,,接收端在收到物理层上交的比特流后,根据首尾的标记,识别帧的开始和结束,将中间的数据部分上交给网络层,然后层层向上传递到应用层。 TCP/IP 分为四层,在发送数据时,每层都要对数据进行封装        ![](https://img-blog.csdnimg.cn/20200625162706296.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3VvbmVsZQ==,size_16,color_FFFFFF,t_70) ## 1.4 服务器收到请求并处理 **服务器接受请求,**接受过程就是把以上步骤逆转过来,参见上图 **HTTPD** 最常见的 HTTPD 有 Linux 上常用的 Apache 和 Nginx,以及 Windows 上的 IIS。 它会监听得到的请求,然后开启一个子进程去处理这个请求。 **处理请求** 接受 TCP 报文后,会对连接进行处理,对HTTP协议进行解析(请求方法、域名、路径等),并且进行一些验证: * 验证是否配置虚拟主机 * 验证虚拟主机是否接受此方法 * 验证该用户可以使用该方法(根据 IP 地址、身份信息等) **重定向** 假如服务器配置了 HTTP 重定向,就会返回一个 `301`永久重定向响应,浏览器就会根据响应,重新发送 HTTP 请求(重新执行上面的过程)。 **URL 重写** 然后会查看 URL 重写规则,如果请求的文件是真实存在的,比如图片、html、css、js文件等,则会直接把这个文件返回。 否则服务器会按照规则把请求重写到 一个 REST 风格的 URL 上。 然后根据动态语言的脚本,来决定调用什么类型的动态文件解释器来处理这个请求。 以 PHP 语言的 MVC 框架举例,它首先会初始化一些环境的参数,根据 URL 由上到下地去匹配路由,然后让路由所定义的方法去处理请求 ### 1.5 服务器返回响应结果 返回响应资源。 ### 1.6关闭TCP连接 (不一定关闭) ### 1.7浏览器解析HTML 浏览器接收到来自服务器的响应资源后,会对资源进行分析。 首先查看 Response header,根据不同状态码做不同的事(比如上面提到的重定向)。 如果响应资源进行了压缩(比如 gzip),还需要进行解压。 然后,对响应资源做缓存。 接下来,根据响应资源里的 [MIME](https://link.zhihu.com/?target=https%3A//developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types) 类型去解析响应内容(比如 HTML、Image各有不同的解析方式) ### 1.8浏览器渲染页面 太长了,[看这里](https://zhuanlan.zhihu.com/p/80551769)吧