zoukankan      html  css  js  c++  java
  • 一次完整的浏览器请求流程

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

    域名解析 --> 发起TCP的3次握手 --> 建立TCP连接后发起http请求 --> 服务器响应http请求,浏览器得到html代码 --> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) --> 浏览器对页面进行渲染呈现给用户

    1.域名解析

    首先Chrome浏览器会解析 www.linux178.com 这个域名(准确的叫法应该是主机名)对应的IP地址。怎么解析到对应的IP地址?

    ① Chrome浏览器 会首先搜索浏览器自身的DNS缓存(缓存时间比较短,大概只有1分钟,且只能容纳1000条缓存),看自身的缓存中是否有www.linux178.com 对应的条目,而且没有过期,如果有且没有过期则解析到此结束。

        注:我们怎么查看Chrome自身的缓存?可以使用 chrome://net-internals/#dns 来进行查看

    ② 如果浏览器自身的缓存里面没有找到对应的条目,那么Chrome会搜索操作系统自身的DNS缓存,如果找到且没有过期则停止搜索解析到此结束.

         注:怎么查看操作系统自身的DNS缓存,以Windows系统为例,可以在命令行下使用 ipconfig /displaydns 来进行查看  

    ③ 如果在Windows系统的DNS缓存也没有找到,那么尝试读取hosts文件(位于C:WindowsSystem32driversetc),看看这里面有没有该域名对应的IP地址,如果有则解析成功。

    ④ 如果在hosts文件中也没有找到对应的条目,浏览器就会发起一个DNS的系统调用,就会向本地配置的首选DNS服务器(一般是电信运营商提供的,也可以使用像Google提供的DNS服务器)发起域名解析请求(通过的是UDP协议向DNS的53端口发起请求,这个请求是递归的请求,也就是运营商的DNS服务器必须得提供给我们该域名的IP地址),运营商的DNS服务器首先查找自身的缓存,找到对应的条目,且没有过期,则解析成功。如果没有找到对应的条目,则有运营商的DNS代我们的浏览器发起迭代DNS解析请求,它首先是会找根域的DNS的IP地址(这个DNS服务器都内置13台根域的DNS的IP地址),找打根域的DNS地址,就会向其发起请求(请问www.linux178.com这个域名的IP地址是多少啊?),根域发现这是一个顶级域com域的一个域名,于是就告诉运营商的DNS我不知道这个域名的IP地址,但是我知道com域的IP地址,你去找它去,于是运营商的DNS就得到了com域的IP地址,又向com域的IP地址发起了请求(请问www.linux178.com这个域名的IP地址是多少?),com域这台服务器告诉运营商的DNS我不知道www.linux178.com这个域名的IP地址,但是我知道linux178.com这个域的DNS地址,你去找它去,于是运营商的DNS又向linux178.com这个域名的DNS地址(这个一般就是由域名注册商提供的,像万网,新网等)发起请求(请问www.linux178.com这个域名的IP地址是多少?),这个时候linux178.com域的DNS服务器一查,诶,果真在我这里,于是就把找到的结果发送给运营商的DNS服务器,这个时候运营商的DNS服务器就拿到了www.linux178.com这个域名对应的IP地址,并返回给Windows系统内核,内核又把结果返回给浏览器,终于浏览器拿到了www.linux178.com  对应的IP地址,该进行一步的动作了。

    看下图抓包截图:

    使用命令 wget www.linux178.com 来请求,发现直接使用chrome浏览器请求时,干扰请求比较多,所以就使用wget命令来请求,不过使用wget命令只能把index.html请求回来,并不会对index.html中包含的静态资源(js、css等文件)进行请求。

    wKioL1LSWzzxRParAAKbC85UJtE371.jpg

    2.发起TCP的3次握手

    拿到域名对应的IP地址之后,User-Agent(一般是指浏览器)会根据url中输入的端口向服务器的WEB程序(常用的有httpd,nginx等)发起TCP的连接请求。这个连接请求经过网络中层层的路由到达机房路由之后,防火墙判断当前端口是否开放,如果开放则进入到服务器网卡,然后是进入到内核的TCP/IP协议栈(用于识别该连接请求,解封包,一层一层的剥开),最终到达WEB程序(本文就以Nginx为例),最终建立了TCP/IP的连接。

    如下图:

    wKioL1LSW6rjI1nhAAE63Uv8ZRY731.jpg

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

    进过TCP3次握手之后,浏览器发起了http的请求(看第12包),使用的http的方法 GET 方法,请求的URL是 / ,协议是HTTP/1.0

    wKioL1LSXDmgmVT_AAFUErYF2ys832.jpg

    下面是第12号包的详细内容:

    wKiom1LSXHiCgHkBAAKtTT2l-Ac152.jpg

    以上的报文是HTTP请求报文。

    下面是Chrome发起的http请求报文头部信息

    wKioL1LSXMqCjyIQAAESKm-mkV8876.jpg

    其中

    Accept  就是告诉服务器端,我接受那些MIME类型

    Accept-Encoding  这个看起来是接受那些压缩方式的文件

    Accept-Lanague   告诉服务器能够发送哪些语言

    Connection       告诉服务器支持keep-alive特性

    Cookie           每次请求时都会携带上Cookie以方便服务器端识别是否是同一个客户端

    Host             用来标识请求服务器上的那个虚拟主机,比如Nginx里面可以定义很多个虚拟主机

                    那这里就是用来标识要访问那个虚拟主机。

    User-Agent       用户代理,一般情况是浏览器,也有其他类型,如:wget curl 搜索引擎的蜘蛛等    

      

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

    看下图 第12号包是http请求包,第32包是http响应包

    服务器端WEB程序接收到http请求以后,就开始处理该请求,处理之后就返回给浏览器html文件。

    wKiom1LSXVeQETJrAAaV9VlbbBo896.jpg

    第32号包 是服务器返回给客户端http响应包(200 ok 响应的MIME类型是text/html),代表这一次客户端发起的http请求已成功响应。200 代表是的 响应成功的状态码,还有其他的状态码如下:

    1xx: 信息性状态码

        100, 101

    2xx: 成功状态码

        200:OK

    3xx: 重定向状态码

        301: 永久重定向, Location响应首部的值仍为当前URL,因此为隐藏重定向;

        302: 临时重定向,显式重定向, Location响应首部的值为新的URL

        304:Not Modified  未修改,比如本地缓存的资源文件和服务器上比较时,发现并没有修改,服务器返回一个304状态码,

                            告诉浏览器,你不用请求该资源,直接使用本地的资源即可。

    4xx: 客户端错误状态码

        404: Not Found  请求的URL资源并不存在

    5xx: 服务器端错误状态码

        500: Internal Server Error  服务器内部错误

        502: Bad Gateway  前面代理服务器联系不到后端的服务器时出现

        504:Gateway Timeout  这个是代理能联系到后端的服务器,但是后端的服务器在规定的时间内没有给代理服务器响应

    用Chrome浏览器看到的响应头信息:

    wKioL1LSXgCDWDvyAADfe7wzmKk795.jpg

    Connection            使用keep-alive特性

    Content-Encoding      使用gzip方式对资源压缩

    Content-type          MIME类型为html类型,字符集是 UTF-8

    Date                  响应的日期

    Server                使用的WEB服务器

    那到底服务器端接收到http请求后是怎么样生成html文件?

    假设服务器端使用nginx+php(fastcgi)架构提供服务

    ① nginx读取配置文件

    我们在浏览器的地址栏里面输入的是 http://www.linux178.com (http://可以不用输入,浏览器会自动帮我们添加),其实完整的应该是http://www.linux178.com./ 后面还有个点(这个点代表就是根域,一般情况下我们不用输入,也不显示),后面的/也是不用添加,浏览器会自动帮我们添加(且看第3部那个图里面的URL),那么实际请求的URL是http://www.linux178.com/,那么好了Nginx在收到 浏览器 GET / 请求时,会读取http请求里面的头部信息,根据Host来匹配 自己的所有的虚拟主机的配置文件的server_name,看看有没有匹配的,有匹配那么就读取该虚拟主机的配置,发现如下配置:

    1
    root /web/echo

    通过这个就知道所有网页文件的就在这个目录下 这个目录就是/ 当我们http://www.linux178.com/时就是访问这个目录下面的文件,例如访问http://www.linux178.com/index.html,那么代表/web/echo下面有个文件叫index.html

    1
    index index.html index.htm index.php

    通过这个就能得知网站的首页文件是那个文件,也就是我们在入http://www.linux178.com/ ,nginx就会自动帮我们把index.html(假设首页是index.php 当然是会尝试的去找到该文件,如果没有找到该文件就依次往下找,如果这3个文件都没有找到,那么就抛出一个404错误)加到后面,那么添加之后的URL是/index.php,然后根据后面的配置进行处理

    1
    2
    3
    4
    5
    6
    7
    location ~ .*.php(/.*)*$ {
       root /web/echo;
       fastcgi_pass   127.0.0.1:9000;
       fastcgi_index  index.php;
       astcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
       include        fastcgi_params;
    }

    这一段配置指明凡是请求的URL中匹配(这里是启用了正则表达式进行匹配) *.php后缀的(后面跟的参数)都交给后端的fastcgi进程进行处理。

    ② 把php文件交给fastcgi进程去处理

    于是nginx把/index.php这个URL交给了后端的fastcgi进程处理,等待fastcgi处理完成后(结合数据库查询出数据,填充模板生成html文件)返回给nginx一个index.html文档,Nginx再把这个index.html返回给浏览器,于是乎浏览器就拿到了首页的html代码,同时nginx写一条访问日志到日志文件中去。

      

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

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

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

    wKiom1LSX_PT06f3AAF_5iS18UA331.jpg

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

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

    自此一次完整的HTTP事务宣告完成.

    转载自http://linux5588.blog.51cto.com/65280/1351007

  • 相关阅读:
    20165231 2017-2018-2《Java程序设计》课程总结
    2017-2018-2 20165231 实验五 网络编程与安全
    2017-2018-2 20165231 实验四 Android程序设计
    2017-2018-2 20165231 实验三 敏捷开发与XP实践
    20165231 2017-2018-2 《Java程序设计》第9周学习总结
    20165231 结对编程四则运算第二阶段总结
    20165231 2017-2018-2 《Java程序设计》第8周学习总结
    20165115 第二周学习总结
    20165115 第一周学习总结
    20165115 C语言学习心得
  • 原文地址:https://www.cnblogs.com/lidong94/p/8309130.html
Copyright © 2011-2022 走看看