一个http请求的全过程是怎样的?

在理解http请求之前先认识几个知识点:

HTTP和浏览器原理*
1.浏览器输入 url 到呈现出内容发生了什么
(1)浏览器根据请求的URL交给DNS域名解析,找到真实IP,向服务器发起请求;
(2)服务器交给后台处理完成后返回数据,浏览器接收文件(HTML、JS、CSS、图象等);
(3)浏览器对加载到的资源(HTML、JS、CSS等)进行语法解析,建立相应的内部数据结构(如HTML的DOM);
(4)载入解析到的资源文件,渲染页面,完成。
2.浏览器渲染的过程
(1)浏览器将获取的HTML文档并解析成DOM树。
(2)处理CSS标记,构成层叠样式表模型CSSOM(CSS Object Model)。
(3)将DOM和CSSOM合并为渲染树(rendering tree)将会被创建,代表一系列将被渲染的对象。
(4)渲染树的每个元素包含的内容都是计算过的,它被称之为布局layout。浏览器使用一种流式处理的方法,只需要一次pass绘制操作就可以布局所有的元素。
(5)将渲染树的各个节点绘制到屏幕上,这一步被称为绘制painting.*

3.如何解决跨域问题
(1)CORS跨域
后端修改请求头
header(‘Access-Control-Allow-Origin:*’);允许访问的网址
header(‘Access-Control-Allow-Method:POST,GET’);允许访问的方式
(2)JSONP
(3)代理机制

4.重绘和重排
(1)重排负责元素的几何属性更新,重绘负责元素的样式更新
(2)重排必然带来重绘,但是重绘未必带来重排
(3)减少重排和重绘:减少js操纵dom元素的集合属性 批量修改DOM 缓存布局信息

5.浏览器如何实现缓存(强缓存和协商缓存)
(1)先根据这个资源的http header判断它是否命中强缓存,如果命中,则直接从本地缓存中获取资源,不会则向服务器请求 资源。
(2)当强缓存没有命中时,客户端会发送请求到服务器,服务器通过另一些request header验证这个资源是否命中协商缓存,这个过程成为http再验证,如果命中,服务器直接返回请求而不返回资源,而是告诉客户端直接从缓存中获取,客户端收到返回后就直接从客户端获取资源
(3)强缓存和协商缓存的共同之处在于:如果命中缓存,服务器不会返回资源;区别是:强缓存不发送请求到服务器,但是协商缓存会发送请求到服务器
(4)当协商缓存没有命中时,服务器会返回资源给客户端
(5)当ctrl+F5强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存
(6)当F5刷新页面时,跳过强缓存但会检查协商缓存

6.前端存储技术(cookie、session、localStorage、sessionStorage)

                                                                http请求过程图示

一、前言

  当我们在浏览器栏输入:http//:www.baidu.com 的时候,具体发生了什么呢?这个请求是怎么到达服务器及返回结果的呢                                        

● URG:紧急标志。紧急标志为"1"表明该位有效。特点是让数据插队。URG=1的就会在缓存中被提前到第一个传输。

● ACK:确认标志。表明确认编号栏有效。大多数情况下该标志位是置位的。TCP报头内的确认编号栏内包含的确认编号(w+1)为下一个预期的序列编号,同时提示远端系统已经成功接收所有数据。

● PSH:推标志。就是接收端的URG,将PSH=1的数据j尽快接收。该标志置位时,接收端不将该数据进行队列处理,而是尽可能快地将数据转由应用处理。在处理Telnet或rlogin等交互模式的连接时,该标志总是置位的。

● RST:复位标志。用于复位相应的TCP连接。

● SYN:同步标志。连接请求/连接接受。表明同步序列编号栏有效。该标志仅在三次握手建立TCP连接时有效。它提示TCP连接的服务端检查序列编号,该序列编号为TCP连接初始端(一般是客户端)的初始序列编号。在这里,可以把TCP序列编号看作是一个范围从0到4,294,967,295的32位计数器。通过TCP连接交换的数据中每一个字节都经过序列编号。在TCP报头中的序列编号栏包括了TCP分段中第一个字节的序列编号。

● FIN:结束标志。已经发送完,请求释放连接。                      

二、概述

  1. 浏览器进行DNS域名解析(就是域名到IP地址的转换过程),得到对应的IP地址
  2. 根据这个IP,找到对应的服务器建立连接(三次握手)
  3. 建立TCP连接后发起HTTP请求(一个完整的http请求报文)
  4. 服务器响应HTTP请求,浏览器得到html代码(服务器如何响应)
  5. 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等)
  6. 浏览器对页面进行渲染呈现给用户
  7. 服务器关闭TCP连接(四次挥手)

三、过程详解

1.DNS域名解析

  1. 首先会搜索浏览器自身的DNS缓存(缓存时间比较短,大概只有1分钟,且只能容纳1000条缓存);
  2. 如果浏览器自身的缓存里面没有找到,那么浏览器会搜索系统自身的DNS缓存;
  3. 如果还没有找到,那么尝试从 hosts文件里面去找;
  4. 在前面三个过程都没获取到的情况下,浏览器就会发起一个DNS的系统调用,就会向本地配置的首选DNS服务器(一般是电信运营商提供的,也可以使用像Google提供的DNS服务器)发起域名解析请求(通过的是UDP协议向DNS的53端口发起请求,这个请求是递归的请求,也就是运营商的DNS服务器必须得提供给我们该域名的IP地址)。

2、TCP三次握手

  三次握手: 服务端新建套接字,绑定地址信息后开始监听,进入LISTEN状态。客户端新建套接字绑定地址信息后调用connect,发送连接请求SYN,并进入SYN_SENT状态,等待服务器的确认。服务端一旦监听到连接请求,就会将连接放入内核等待队列中,并向客户端发送SYN和确认报文段ACK,进入SYN_RECD状态。客户端收到SYN+ACK报文后向服务端发送确认报文段ACK,并进入ESTABLISHED状态,开始读写数据。服务端一旦收到客户端的确认报文,就进入ESTABLISHED状态,就可以进行读写数据了。

  1. 为什么握手是三次,而不是两次或者四次?

  答:两次不安全,四次没必要。tcp通信需要确保双方都具有数据收发的能力,得到ACK响应则认为对方具有数据收发的能力,因此双方都要发送SYN确保对方具有通信的能力。

  • 第一次握手是客户端发送SYN,服务端接收,服务端得出客户端的发送能力和服务端的接收能力都正常;

  • 第二次握手是服务端发送SYN+ACK,客户端接收,客户端得出客户端发送接收能力正常,服务端发送接收能力也都正常,但是此时服务器并不能确认客户端的接收能力是否正常;

  • 第三次握手客户端发送ACK,服务器接收,服务端才能得出客户端发送接收能力正常,服务端自己发送接收能力也都正常。

  2. 三次握手可以携带数据吗?

  答:第一次、第二次握手不可以携带数据,而第三次握手是可以携带数据的。假设第一次可以携带数据,如果有人恶意攻击服务器,每次都在第一次握手中的SYN报文放入大量数据,重复发送大量SYN报文,此时服务器会花费大量内存空间来缓冲这些报文,服务器就更容易被攻击了。

  3. TCP三次握手失败,服务端会如何处理?

  答:握手失败的原因有两种,第一种是服务端没有收到SYN,则什么都不做;第二种是服务端回复了SYN+ACK后,长时间没有收到ACK响应,则超时后就会发送RST重置连接报文,释放资源。

  4. ISN代表什么?意义何在?ISN是固定不变的吗?ISN为何要动态随机

  答:ISN全称是Initial Sequence Number,是TCP发送方的字节数据编号的原点,告诉对方我要开始发送数据的初始化序列号。

  ISN如果是固定的,攻击者很容易猜出后序的确认号,为了安全起见,避免被第三方猜到从而发送伪造的RST报文,因此ISN是动态生成的。

  5. 什么是半连接队列

  答:服务器第一次收到客户端的SYN之后,就会处于SYN_RECD状态,此时双方还没有完全建立连接。服务器会把这种状态下的请求连接放在一个队列里,我们把这种队列称之为半连接队列。当然还有一个全连接队列,就是已经完成三次握手,建立起来连接的就会放在全连接队列中,如果队列满了就有可能出现丢包现象。

3、 发起HTTP请求

  HTTP是一个客户端和服务器端请求和应答的标准(TCP)。客户端是终端用户,服务器端是网站。通过使用web浏览器、网络爬虫或者其它的工具,客户端发起一个到服务器上指定端口(默认端口为80)的HTTP协议进行,否则无法连接。

  通俗来讲,他就是计算机通过网络进行通信的规则,是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据。目前任何终端之间进行任何一种通信都必须按照HTTP协议进行,否则无法连接。

  HTTP请求报文:

  一个HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求数据4个部分组成。

 1)请求行

  请求行分为三个部分:请求方法、请求地址和协议版本。

  请求方法

        HTTP/1.1 定义的请求方法有8种:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。

  最常用的两种GET和POST,如果是RESTful接口的话一般会用到GET、POST、DELETE、PUT。

  请求地址

              URL:统一资源定位符,是一种自愿位置的抽象唯一识别方法。

    组成:<协议>://<主机>:<端口>/<路径>。

    端口和路径有时可以省略(HTTP默认端口号是80)。

 2)请求头部

    请求头部为请求报文添加了一些附加信息,由“名/值”对组成,每行一对,名和值之间使用冒号分隔。

    请求头部的最后会有一个空行,表示请求头部结束,接下来为请求数据,这一行非常重要,必不可少。

 3)请求数据

    可选部分,比如GET请求就没有请求数据。
 

4、服务器响应HTTP请求

   接收到HTTP请求之后,就轮到负载均衡登场了,它位于网站的最前端,把短时间内较高的访问量分摊到不同机器上处理。负载均衡方案有软件、硬件两种。软件方案常见的就是NGINX了。

   Nginx的作用主要有两个1,处理静态文件请求,2转发请求给后端服务器。然后后端服务器查询数据库返回数据。数据返回给客户端仍然通过HTTP协议传输。

   HTTP响应报文主要由状态行、响应头部、空行以及响应数据组成。

  1) 状态行:由3部分组成,分别为:协议版本,状态码,状态码描述。

   其中协议版本与请求报文一致,状态码描述是对状态码的简单描述,所以这里就只介绍状态码。 一些常见的状态码如下:

   2)响应头部

    与请求头部类似,为响应报文添加了一些附加信息。

   3)响应数据

    用于存放需要返回给客户端的数据信息。

  上面的 HTTP 响应中,响应头中的 Content-Length 同样用于表示消息体的字节数。Content-Type 表示消息体的类型,通常浏览网页其类型是HTML,当然还会有其他类型,比如图片、视频等。

5、浏览器解析

  浏览器拿到index.html文件后,就开始解析其中的html代码,遇到js/css/image等静态资源时,就向服务器端去请求下载(会使用多线程下载,每个浏览器的线程数不一样),这个时候就用上keep-alive特性了,建立一次HTTP连接,可以请求多个资源,下载资源的顺序就是按照代码里的顺序,但是由于每个资源大小不一样,而浏览器又多线程请求请求资源,所以显示的顺序并不一定是代码里面的顺序。

  浏览器在请求静态资源时(在未过期的情况下),向服务器端发起一个http请求(询问自从上一次修改时间到现在有没有对资源进行修改),如果服务器端返回304状态码(告诉浏览器服务器端没有修改),那么浏览器会直接读取本地的该资源的缓存文件。

6、浏览器进行页面渲染

  最后,浏览器利用自己内部的工作机制,把请求的静态资源和html代码进行渲染,渲染之后呈现给用户,浏览器是一个边解析边渲染的过程。

7、服务器关闭TCP连接

  一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接。而关闭TCP连接就需要进行四次挥手了。

  中断连接端可以是客户端,也可以是服务器端。

  四次挥手:

  • 客户端主动调用close时,向服务端发送结束报文段FIN报,同时进入FIN_WAIT1状态;
  • 服务器会收到结束报文段FIN报,服务器返回确认报文段ACK并进入CLOSE_WAIT状态,此时如果服务端有数据要发送的话,客户端依然需要接收。客户端收到服务器对结束报文段的确认,就会进入到FIN_WAIT2状态,开始等待服务器的结束报文段;
  • 服务器端数据发送完毕后,当服务器真正调用close关闭连接时,会向客户端发送结束报文段FIN包,此时服务器进入LAST_ACK状态,等待最后一个ACK的到来;
  • 客户端收到服务器发来的结束报文段, 进入TIME_WAIT, 并发出送确认报文段ACK;服务器收到了对结束报文段确认的ACK,进入CLOSED状态,断开连接。而客户端要等待2MSL的时间,才会进入到CLOSED状态。

    注:SYN:同步位,SYN=1,表示要进行一个连接请求;

      FIN:表示关闭连接;

      ACK:表示响应,确认位,ACK=1,确认有效,ACK=0,确认无效;

      seq:序号,机器随机生成;

      ack:确认号,对方发送序号+1(ack=seq+1);

      PSH:表示有 DATA数据传输;

      RST表示连接重置。

  其中,ACK是可能与SYN,FIN等同时使用的,比如SYN和ACK可能同时为1,它表示的就是建立连接之后的响应;如果只        是单个的一个SYN,它表示的只是建立连接。但SYN与FIN是不会同时为1的,因为前者表示的是建立连接,而后者表示的是断开连接。RST一般是在FIN之后才会出现为1的情况,表示的是连接重置。

 1. 为什么握手是三次,而挥手时需要四次呢?

  答:其实在TCP握手的时候,接收端将SYN包和ACK确认包合并到一个包中发送的,所以减少了一次包的发送。对于四次挥手,由于TCP是全双工通信,主动关闭方发送FIN请求不代表完全断开连接,只能表示主动关闭方不再发送数据了。

  而接收方可能还要发送数据,就不能立即关闭服务器端到客户端的数据通道,所以就不能将服务端的FIN包和对客户端的ACK包合并发送,只能先确认ACK,等服务器无需发送数据时在发送FIN包,所以四次挥手时需要四次数据包的交互。

 2. TIME_WAIT状态有什么作用,为什么主动关闭方没有直接进入CLOSED状态释放资源?

  答:如果主动关闭方进入CLOSED状态后,被动关闭方发送FIN包后没有得到ACK确认,超时后就会重传一个FIN包。如果客户端没有TIME_WAIT状态而直接进入CLOSED状态释放资源,下次启动新的客户端就可能使用了与之前客户端相同的地址信息,有两个危害:

  • 第一种是这个刚启动的新的客户端绑定地址成功时,就会收到了一个重传的FIN包,对新连接就会造成影响。
  • 第二种是如果该新客户端向相同的服务端发送SYN连接请求,但是此时服务端处于LAST_ACK状态,要求收到的是ACK而不是SYN,因此就会发送RST重新建立请求。

 3. 为什么TIME_WAIT状态需要经过2MSL才能进入CLOASE状态?

  答:MSL指的是报文在网络中最大生存时间。在客户端发送对服务端的FIN确认包ACK后,这个ACK包有可能到达不了,服务器端如果接收不到ACK包就会重新发送FIN包。

  所以客户端发送ACK后需要留出2MSL时间(ACK到达服务器器+服务器发送FIN重传包,一来一回)等待确认服务器端确实收到了ACK包。也就是说客户端如果等待2MSL时间也没收到服务器端重传的FIN包,则就可以确认服务器已经收到客户端发送的ACK包,则结束TCP连接。

  然而如果浏览器或者服务器在其头信息加入了这行代码:

  Connection:keep-alive

   TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽

 4. 一台主机上出现大量的TIME_WAIT是什么原因?应该如何处理?

   答:TIME_WAIT是主动关闭方出现的,一台主机出现大量的TIME_WAIT证明这台主机上发起大量的主动关闭连接。常见于一些爬虫服务器。这时候我们应该调整TIME_WAIT的等待时间,或者开启套接字地址重用选项。

 5. 一台主机上出现大量的CLOSE_WAIT是什么原因?应该如何处理?

   答:CLOSE_WAIT是被动关闭方收到FIN请求进行回复之后的状态,等待上层程序进一步处理,若出现大量CLOSE_WAIT,有可能是被动关闭方主机程序中忘了最后一步断开连接后调用close释放资源。这是一个 BUG,只需要加上对应的 close 即可解决问题。

 6. TCP连接管理中的保活机制

   答:TCP通信中,若两端长时间没有数据往来,则这时候每隔一段时间,服务端会向客户端发送一个保活探测数据报,要求客户端进行回复。若连续多次没有收到响应,就认为连接已经断开。长时间默认为7200s,每隔一段时间默认为75s,连续多次无响应默认为9次。这些数据都可以在套接字中修改,接口:Setsockopt。

猜你喜欢

转载自blog.csdn.net/weixin_51225684/article/details/129147119