一次HTTP请求的完整过程——协议篇(DNS、TCP、HTTP)

一、大致流程

  • 根据域名和 DNS 解析到服务器的IP地址 (DNS + CDN)
  • 通过ARP协议获得IP地址对应的物理机器的MAC地址
  • 浏览器对服务器发起 TCP 3 次握手
  • 建立 TCP 连接后发起 HTTP 请求报文
  • 服务器响应 HTTP 请求,将响应报文返回给浏览器
  • 短连接情况下,请求结束则通过 TCP 四次挥手关闭连接,长连接在没有访问服务器的若干时间后,进行连接的关闭
  • 浏览器得到响应信息中的 HTML 代码, 并请求 HTML 代码中的资源(如js、css、图片等)
  • 浏览器对页面进行渲染并呈现给用户

二、深入分析

2.1 概括

在网络协议方面,可以从三个方面深入分析

  1. DNS解析过程
  2. TCP连接过程(三次握手、四次挥手)
  3. HTTP请求响应过程

2.2 DNS协议

2.2.1 DNS解析过程

  1.在浏览器中输入www.qq.com域名,操作系统会先检查浏览器会缓存是否有记录, 然后再检查自己本地的hosts文件是否有这个网址映射关系,如果有,就先调用这个IP地址映射,完成域名解析。
  2.如果hosts里没有这个域名的映射,则查找本地DNS解析器缓存,是否有这个网址映射关系,如果有,直接返回,完成域名解析。

  3.如果hosts与本地DNS解析器缓存都没有相应的网址映射关系,首先会找TCP/IP参数中设置的首选DNS服务器,在此我们叫它本地DNS服务器,此服务器收到查询时,如果要查询的域名,包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性。

  4.如果要查询的域名,不由本地DNS服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析,此解析不具有权威性。

  5.如果本地DNS服务器本地区域文件与缓存解析都失效,则根据本地DNS服务器的设置(是否设置转发器)进行查询,如果未用转发模式,本地DNS就把请求发至 “根DNS服务器”,“根DNS服务器”收到请求后会判断这个域名(.com)是谁来授权管理,并会返回一个负责该顶级域名服务器的一个IP。本地DNS服务器收到IP信息后,将会联系负责.com域的这台服务器。这台负责.com域的服务器收到请求后,如果自己无法解析,它就会找一个管理.com域的下一级DNS服务器地址(qq.com)给本地DNS服务器。当本地DNS服务器收到这个地址后,就会找qq.com域服务器,重复上面的动作,进行查询,直至找到www.qq.com主机。

  6.如果用的是转发模式,此DNS服务器就会把请求转发至上一级DNS服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根DNS或把转请求转至上上级,以此循环不管是本地DNS服务器用是是转发,还是根提示,最后都是把结果返回给本地DNS服务器,由此DNS服务器再返回给客户机。

  DNS主要是通过UDP通信,报文结构主要分为头部Header、查询部分Question、应答部分Answer/Authority/Addition

2.2.2 DNS用的是TCP协议还是UDP协议

  DNS占用53号端口,同时使用TCP和UDP协议。那么DNS在什么情况下使用这两种协议?

  DNS在区域传输的时候使用TCP协议,其他时候(如域名解析)使用UDP协议

  DNS区域传输的时候使用TCP协议:

    1.辅域名服务器会定时(一般3小时)向主域名服务器进行查询以便了解数据是否有变动。如有变动,会执行一次区域传送,进行数据同步。区域传送使用TCP而不是UDP,因为数据同步传送的数据量比一个请求应答的数据量要多得多

    2.TCP是一种可靠连接,保证了数据的准确性

  域名解析时使用UDP协议:

    客户端向DNS服务器查询域名,一般返回的内容都不超过512字节,用UDP传输即可。不用经过三次握手,这样DNS服务器负载更低,响应更快。理论上说,客户端也可以指定向DNS服务器查询时用TCP,但事实上,很多DNS服务器进行配置的时候,仅支持UDP查询包

2.2.2 DNS为什么用TCP和UDP

  DNS同时占用UDP和TCP端口53是公认的,这种单个应用协议同时使用两种传输协议的情况在TCP/IP栈也算是个另类。但很少有人知道DNS分别在什么情况下使用这两种协议。 

  先简单介绍下TCP与UDP。 

  TCP是一种面向连接的协议,提供可靠的数据传输,一般服务质量要求比较高的情况,使用这个协议。UDP---用户数据报协议,是一种无连接的传输层协议,提供面向事务的简单不可靠

信息传送服务。 

  TCP与UDP的区别: 

    UDP和TCP协议的主要区别是两者在如何实现信息的可靠传递方面不同。TCP协议中包含了专门的传递保证机制,当数据接收方收到发送方传来的信息时,会自动向发送方发出确认

消息;发送方只有在接收到该确认消息之后才继续传送其它信息,否则将一直等待直到收到确认信息为止。 与TCP不同,UDP协议并不提供数据传送的保证机制。如果在从发送方到接收方的

传递过程中出现数据报的丢失,协议本身并不能做出任何检测或提示。因此,通常人们把UDP协议称为不可靠的传输协议。相对于TCP协议,UDP协议的另外一个不同之处在于如何接收突发

性的多个数据报。不同于TCP,UDP并不能确保数据的发送和接收顺序。事实上,UDP协议的这种乱序性基本上很少出现,通常只会在网络非常拥挤的情况下才有可能发生。 

    既然UDP是一种不可靠的网络协议,那么还有什么使用价值或必要呢?其实不然,在有些情况下UDP协议可能会变得非常有用。因为UDP具有TCP所望尘莫及的速度优势。虽然TCP协议中植入了各种安全保障功能,但是在实际执行的过程中会占用大量的系统开销,无疑使速度受到严重的影响。反观UDP由于排除了信息可靠传递机制,将安全和排序等功能移交给上层应用来完成,极大降低了执行时间,使速度得到了保证。 

  DNS在进行区域传输的时候使用TCP协议,其它时候则使用UDP协议; 

  DNS的规范规定了2种类型的DNS服务器,一个叫DNS服务器,一个叫辅助DNS服务器。在一个区中主DNS服务器从自己本机的数据文件中读取该区的DNS数据信息,而辅助DNS服务器则从区的主DNS服务器中读取该区的DNS数据信息。当一个辅助DNS服务器启动时,它需要与主DNS服务器通信,并加载数据信息,这就叫做区传送(zone transfer)。 

2.2.3 DNS为什么用TCP和UDP

  首先了解以下TCP与UDP传送字节的长度限制:

    在以太网当中MTU是1500:

      UDP 包的大小就应该是 1500 - IP头(20) - UDP头(8) = 1472(Bytes)
      TCP 包的大小就应该是 1500 - IP头(20) - TCP头(20) = 1460 (Bytes)

    在英特网当中标准MTU值为576字节:

      UDP 包的大小就应该是 576 - IP头(20) - UDP头(8) = 548 (Bytes)
      TCP 包的大小就应该是 576 - IP头(20) - TCP头(20) = 536 (Bytes)

  区域传送使用TCP,主要由以下两点考虑: 

     1、TCP是一种可靠的连接,保证了数据的准确性 

     2、辅域名服务器会定时(一般时3小时)向主域名服务器进行查询以便了解数据是否有变动。如有变动,则会执行一次区域传送,进行数据同步。区域传送将使用TCP而不是UDP,因为数据同步传送的数据量比一个请求和应答的数据量要多得多 

2.2.4 递归查询与迭代查询

 一、主机向本地域名服务器的查询一般都是采用递归查询

        所谓递归查询就是:如果主机所询问的本地域名服务器不知道被查询的域名的IP地址,那么本地域名服务器就以DNS客户的身份向其它根域名服务器继续发出查询请求报文(即替主机继续查询),而不是让主机自己进行下一步查询。因此,递归查询返回的查询结果或者是所要查询的IP地址,或者是报错,表示无法查询到所需的IP地址。

二、本地域名服务器向根域名服务器的查询的迭代查询

  迭代查询的特点:当根域名服务器收到本地域名服务器发出的迭代查询请求报文时,要么给出所要查询的IP地址,要么告诉本地服务器:“你下一步应当向哪一个域名服务器进行查询”。然后让本地服务器进行后续的查询。根域名服务器通常是把自己知道的顶级域名服务器的IP地址告诉本地域名服务器,让本地域名服务器再向顶级域名服务器查询。顶级域名服务器在收到本地域名服务器的查询请求后,要么给出所要查询的IP地址,要么告诉本地服务器下一步应当向哪一个权限域名服务器进行查询。最后,知道了所要解析的IP地址或报错,然后把这个结果返回给发起查询的主机

 

  递归客户端只发一次请求,要求对方给出最终结果

  迭代客户端发出一次请求,对方如果没有授权回答,它就会返回一个能解答这个查询的其它名称服务器列表,客户端会再向返回的列表中发出请求,直到找到最终负责所查域名的名称服务器,从它得到最终结果

  授权回答向dns服务器查询一个域名,刚好这个域名是本服务器负责,返回的结果就是授权回答

  从递归和迭代查询可以看出:

    客户端-本地dns服务端:这部分属于递归查询。

    本地dns服务端---外网:这部分属于迭代查询。

  递归查询时,返回的结果只有两种:查询成功或查询失败

  迭代查询,又称作重指引,返回的是最佳的查询点或者主机地址

 

2.2.5 DNS缓存

  • 浏览器缓存 -浏览器会缓存 DNS 记录一段时间。有趣的是,操作系统不会告诉浏览器每个 DNS 记录的生存时间,因此浏览器将它们缓存一段固定的时间(不同浏览器不同,2 到 30 分钟)。
  • 操作系统缓存– 如果浏览器缓存不包含所需的记录,浏览器会进行系统调用(Windows 中的 gethostbyname)。操作系统有自己的缓存(hosts文件和本地DNS缓存)。
  • 路由器缓存- 请求继续发送到您的路由器,路由器通常有自己的 DNS 缓存
  • ISP DNS 缓存– 下一个检查的地方是缓存 ISP 的 DNS 服务器。自然而然地带有缓存。

 

2.3 TCP 连接过程(3次握手 4次挥手)

  • 三次握手
    在这里插入图片描述
    第一步:客户端向服务端发送一份特殊的 TCP 报文,该报文并不包含应用层的数据,是一份特殊的报文,它的 TCP 首部中 SYN 字段值为 1 。除此之外,客户端还会随机生成一个初始序号,填在报文的「序号」字段,代表当前报文的序号是这个,并且我后续的分组会基于这个序号递增。然后该报文将会经网络层、链路层、物理层发送到服务端。
    第二步:如果分组丢失了,那么客户端会经过某个时间间隔再次尝试发送。而如果分组准确的到达服务端了,服务端拆开 TCP 首部会看到,这是一个特殊的 SYN 握手报文,于是为此次连接分配缓存等资源。
    接着服务端开始构建响应报文,SYN 是一个用于同步需要的字段,响应报文中依然会被置为 1,并且服务端也将随机生成一个初始序号放置的响应报文的序号字段中。
    最后,服务端还会为响应报文中的确认字段赋值,这个值就是客户端发过来的那个序号值加一。
    整体上的意思就是说,「我同意你的连接请求,我的初始序号为 xxx,你的初始序号我收到了,我等着你的下一个分组到来」
    第三步:客户端收到服务端的响应报文,于是分配客户端 TCP 连接所必须的缓存等资源,于是连接已经建立。
  • 四次挥手
    在这里插入图片描述
    第一步:客户端构建一份特殊的 TCP 报文,该报文首部字段 FIN 被置为 1,然后发送该报文。
    第二步:服务端收到该特殊的 FIN 报文,于是响应客户端一个 ACK 报文,告诉客户端,请求关闭的报文已经收到,我正在处理。
    第三步:服务端发送一个 FIN 报文,告诉客户端,我将要关闭连接了。
    第四步:客户端返回一个 ACK 响应报文,告诉服务端,我收到你刚才发的报文了,我已经确认,你可以关闭连接了。

当服务端收到客户端发送的 ACK 响应报文时,将释放服务端用于该 TCP 连接的所有资源,与此同时,客户端也会定时等待一定时间后完全释放自己用于该连接的相关资源。

三、参考文章

https://www.pianshen.com/article/712933935/

http://igoro.com/archive/what-really-happens-when-you-navigate-to-a-url/

https://www.cnblogs.com/qingdaofu/p/7399670.html

https://www.cnblogs.com/jiangzhaowei/p/9273854.html

posted @ 2021-08-29 22:37  Mr-xxx  阅读(1699)  评论(0编辑  收藏  举报