美文网首页架构相关程序员
完整的HTTP事务过程

完整的HTTP事务过程

作者: 5e30faa7d323 | 来源:发表于2017-11-21 16:29 被阅读18次

    当我们在浏览器的地址栏输入 www.linux178.com ,然后回车,回车这一瞬间到看到页面到底发生了什么呢?

    主要经过了如下流程:


    http事务过程

    1、域名解析

    DNS域名解析过程

    过程如下,前两个步骤是本机完成,后面的8个步骤涉及真正的域名解析服务器:

    1)、浏览器检查缓存

    浏览器会检查缓存中有没有这个域名对应的解析过的ip,如果有,那么解析过程结束。浏览器缓存域名是有限制的,浏览器缓存大小和时间都有限制。通常情况是几分钟到几小时不等,域名被缓存的时间限制可以通过TTL属性来设置。缓存时间太短太长都不好,

    如果太短,每次都要重新解析。如果太长,那么一旦域名被解析到的ip有变化,会导致被客户端缓存的域名无法解析到变化后的ip,那么在一段时间内会有用户无法访问网站。

    2)、浏览器检查操作系统缓存

    如果缓存中没有数据,浏览器会查找操作系统缓存中是否有这个域名对应的dns解析结果。操作系统也有域名解析的过程,在windows中可以通过C:\Windows\System32\drivers\etc\hosts文件来设置,在Linux中可以通过/etc/hosts文件来设置,用户可以将任何域名解析到任何能访问ip的地址。

    3)、请求网络配置中的DNS服务器

    以上1、2步骤是浏览器自己完成的,在上图中没有标识出来。
    如果前面无法解析时,就要使用网络配置中的DNS服务器地址了。操作系统会把这个域名发送个LDNS,也就是本地区的域名服务器。这个DNS通常都提供给本地互联网接入的一个DNS解析服务。windows下输入ipconfig,linux通过cat /etc/resolv.conf就可以查询配置DNS服务器。

    这个域名解析服务器性能很好,一般都会缓存域名解析结果,当然缓存时间是收失效时间控制的。大约80%的域名解析到这里就结束了,所以LDNS主要承担了域名的解析工作。

    4)、到Root Server域名服务器中解析

    如果LDNS仍然没有命中,就直接到Root Server域名服务器解析。

    5)、根据域名服务器返回给本地域名服务器一个主域名服务器地址(gTLD),全球13台左右,.com,.cn,.org等。
    6)、本地域名服务器像gLTD发送请求。
    7)、gTLD服务器查询并返回此域名对应的NameServer域名服务器地址,这个NameServer服务器就是注册的域名服务器。
    8)、发送请求到NameServer,根据域名ip映射关系表,找到目标ip。
    9)、返回该域名对应的ip和ttl值,LDNS会缓存这个域名和ip的对应关系,缓存时间由TTL控制。
    10)、把解析结果返回用户,用户根据TTL值缓存在本地系统缓存,解析过程结束。

    时间的解析过程中,可能不止这10步,比如NameServer可能有很多级,或者有一个GTM来负载均衡控制,可能会影响域名解析过程。

    2、发起TCP的3次握手

    拿到域名对应的IP地址之后,User-Agent(一般是指浏览器)会以一个随机端口(1024 < 端口 < 65535)向服务器的WEB程序(常用的有httpd,nginx等)80端口发起TCP的连接请求。这个连接请求(原始的http请求经过TCP/IP4层模型的层层封包)到达服务器端后(这中间通过各种路由设备,局域网内除外),进入到网卡,然后是进入到内核的TCP/IP协议栈(用于识别该连接请求,解封包,一层一层的剥开),还有可能要经过Netfilter防火墙(属于内核的模块)的过滤,最终到达WEB程序(本文就以Nginx为例),最终建立了TCP/IP的连接。

    TCP的3次握手

    1) Client首先发送一个连接试探,ACK=0 表示确认号无效,SYN = 1 表示这是一个连接请求或连接接受报文,同时表示这个数据报不能携带数据,seq = x 表示Client自己的初始序号(seq = 0 就代表这是第0号包),这时候Client进入syn_sent状态,表示客户端等待服务器的回复

    2) Server监听到连接请求报文后,如同意建立连接,则向Client发送确认。TCP报文首部中的SYN 和 ACK都置1 ,ack = x + 1表示期望收到对方下一个报文段的第一个数据字节序号是x+1,同时表明x为止的所有数据都已正确收到(ack=1其实是ack=0+1,也就是期望客户端的第1个包),seq = y 表示Server 自己的初始序号(seq=0就代表这是服务器这边发出的第0号包)。这时服务器进入syn_rcvd,表示服务器已经收到Client的连接请求,等待client的确认。

    3) Client收到确认后还需再次发送确认,同时携带要发送给Server的数据。ACK 置1 表示确认号ack= y + 1 有效(代表期望收到服务器的第1个包),Client自己的序号seq= x + 1(表示这就是我的第1个包,相对于第0个包来说的),一旦收到Client的确认之后,这个TCP连接就进入Established状态,就可以发起http请求了。

    TCP 为什么需要3次握手?

    举个例子:
    假设一个老外在故宫里面迷路了,看到了小明,于是就有下面的对话:
    老外: Excuse me,Can you Speak English?
    小明: yes 。
    老外: OK,I want ...
    在问路之前,老外先问小明是否会说英语,小明回答是的,这时老外才开始问路

    2个计算机通信是靠协议(目前流行的TCP/IP协议)来实现,如果2个计算机使用的协议不一样,那是不能进行通信的,所以这个3次握手就相当于试探一下对方是否遵循TCP/IP协议,协商完成后就可以进行通信了,当然这样理解不是那么准确。

    正规的理解如下:

    在谢希仁著《计算机网络》第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。在另一部经典的《计算机网络》一书中讲“三次握手”的目的是为了解决“网络中存在延迟的重复分组”的问题。这两种不用的表述其实阐明的是同一个问题。

    谢希仁版《计算机网络》中的例子是这样的,“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”。 主要目的防止server端一直等待,浪费资源。

    为什么HTTP协议要基于TCP来实现?

    目前在Internet中所有的传输都是通过TCP/IP进行的,HTTP协议作为TCP/IP模型中应用层的协议也不例外,TCP是一个端到端的可靠的面向连接的协议,所以HTTP基于传输层TCP协议不用担心数据的传输的各种问题

    3、建立TCP连接后发起http请求

    进过TCP3次握手之后,浏览器发起了http的请求,使用的http的方法 GET 方法,请求的URL是 / ,协议是HTTP/1.1

    4、服务器端响应http请求,浏览器得到html代码

    请求头
    请求头名 描述
    Accept 就是告诉服务器端,我接受那些任何类型
    Accept-Encoding 这个看起来是接受那些压缩方式的文件
    Accept-Lanague 告诉服务器能够发送哪些语言
    Connection 告诉服务器支持keep-alive特性
    Cookie 每次请求时都会携带上Cookie以方便服务器端识别是否是同一个客户端
    Host 用来标识请求服务器上的那个虚拟主机,比如Nginx里面可以定义很多个虚拟主机,那这里就是用来标识要访问那个虚拟主机。
    User-Agent 用户代理,一般情况是浏览器

    5、浏览器解析html代码,并请求html代码中的资源

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

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

    6、浏览器对页面进行渲染呈现给用户

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

    参考:一次完整的HTTP事务是怎样一个过程?
    DNS

    相关文章

      网友评论

        本文标题:完整的HTTP事务过程

        本文链接:https://www.haomeiwen.com/subject/jsjwvxtx.html