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

  • 相关阅读:
    内存泄漏 Memory Leaks 内存优化 MD
    Handler Thread 内部类引起内存泄露分析
    为什么不取消注册BroadcastReceiver会导致内存泄漏
    WebChromeClient 简介 API 案例
    WebViewClient 简介 API 案例
    java.net.URI 简介 文档 API
    android.net.Uri 简介 API
    RV 多样式 MultiType 聊天界面 消息类型 MD
    JS函数声明与定义,作用域,函数声明与表达式的区别
    CSS中table tr:nth-child(even)改变tr背景颜色: IE7,8无效
  • 原文地址:https://www.cnblogs.com/lidong94/p/8309130.html
Copyright © 2011-2022 走看看