本次分享http协议,共分为三部分,这是第三部分,主要讲解一个完整的http请求都经过哪些步骤,当我们在地址栏中输入网址,到返回页面都经历了什么

1.输入网址

当我们在浏览器中输入网址的时候,浏览器就已经在只能匹配可能的 url 了,他会从历史纪录,书签等地方查找已经输入的字符串所对应的 url ,然后给出智能提示,,让你可以补全 url 地址,对于 google 的 chrome 浏览器,他甚至会直接从缓存中把网页展示出来,就是说你还没有按下 enter 页面就展示出来了。

2.浏览器查找域名的 IP 地址

  1.请求一旦发起,浏览器数显要做的事情就是解析这个域名,一般来说,浏览器会首先查看浏览器的 DNS 缓存中是否有缓存纪录,如果有就直接展示,否则就查看本地的 Hosts 文件,看看有没有和这个域名对应的规则,如果有的话就直接使用 Hosts 文件里的 IP 地址。

  2.如果本地的 Hosts 文件没有找到对应的 IP 地址,浏览器会发出一个 DNS 请求到本地的 DNS 服务器,本地 DNS 服务器一般都是你网络接入的服务器商提供,如中国电信,中国移动。

  3.查询你输入的网址的 DNS 请求到达本地的 DNS 服务器之后,本地的 DNS 服务器会首先查询他的缓存纪录,如果缓存中有此条纪录,就直接返回结果,此过程是递归的方式查询,如果没有,本地的 DNS 服务器还要向 DNS 根服务器进行查询。

  4.根 DNS 服务器没有纪录具体的域名和 IP 地址的对应关系,而是告诉本地的 DNS 服务器你可以去域服务器上去继续查询,并给出域服务器的地址,此过程是迭代过程。

  5.本地的 DNS 服务器继续向域服务器发出请求,在这个例子中,请求的对象是 .com 域服务器 .com 域服务器收到请求后,也不会直接返回域名和 IP 地址的对应关系,而是告诉本地的 DNS 服务器你的域名和解析服务器的地址。

  6.最后,本地 DNS 服务器向域名的解析服务器发出请求,这时就能收到域名和 IP 地址的对应关系,本地的 DNS 服务器不仅要把 IP 地址返回给用户电脑,还有把这个对应关系保存在缓存中,以便下次用户查询时,可以直接返回结果,加快网络访问。

3.浏览器向 web 服务器发送一个 http 请求

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

  建立了 TCP 连接之后,发起一个 http 请求,一个典型的 http request header 一般需要包括请求的方法,例如 GET 或者 POST 等,不常有的有 PUT,DELETE,HEAD,OPTION 以及 TRACE 方法,一般的浏览器只能发起 GET 或者 POST 请求。

  客户端向服务器端发起 http 请求的时候,会有一些请求信息,请求信息包含三部分:

  •   请求方法 URI 协议/版本呢
  •   请求头(request  header)
  •   请求正文

下面是一个完整的 http 请求的例子

  GET/sample.jsp HTTP/1.1

  Accept:image/gif.image/jpeg,*/*

  Accept-Language:zh-cn

  Connection:Keep-Alive

  Host:localhost

  User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)  
  

  Accept-Encoding:gzip,deflate

  

  username=jinqiao&password=1234

注意:最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。

4.服务器的永久重定向响应

  服务器给浏览器返回一个 301 永久重定向响应,这样浏览器就会访问 " http://www.google.com/ " 而不是 " http://google.com/ " 。

  为什么服务器一定要重定向而不是直接发送给用户想看的网页内容呢?其中一个原因跟网站排名有关系,如果一个网页有两个网址,就像:http://www.yy.com 和 http:/yy.com ,搜索引擎会认为他们是两个网站,结果造成每个搜索连接都减少从而降低排名。而搜索引擎知道 301 永久重定向是什么意思,这样就会把访问带有 www 和不带 www 的网站地址归到同一个排名下。还有就是用不同的地址会造成缓存友好性变差,当一个页面有好几个名字时,他可能会在缓存里出现好几次。

5.浏览器跟踪重定向地址

  现在浏览器知道了 " http://www.google.com "才是要访问的正确地址,所以他会发送里一个 http 请求。

6.服务器处理请求

  经过前面的重重步骤,我们终于将我们的 http 请求发送到了服务器这里,其实前面的重定向已经是到达服务器了,那么,服务器时如何吃力我们的请求的呢?

  后端从在固定的端口接收到 TCP 报文开始,它会对 TCP 连接进行处理,对 http 协议进行解析并按照报文格式进一步封装成 HTTP Request 对象,供上层使用。

  一些大一点的网站会将你的请求到反向代理服务器中,因为当网站访问量非常大,网站越来越慢,一台服务器已经不够用了,于是将同一应用部署到多台服务器上,将大量的用户请求分配给多台机器处理,此时,客户端不是直接通过 http 协议访问某网站应用服务器,而是先请求到 Nginx,Nginx 在请求应用服务器,然后将结果返回给客户端,这里 Nginx 的作用是反向代理服务器。同时也带来了一个好处,其中一台服务器万一挂了,只要还有其他服务器正常运行,就不会影响用户正常使用。

  通过 Nginx 的反向代理,我们到达了 web 服务器,服务器端脚本处理我们的请求,访问我们的数据库,获取需要获取的内容等等。

7.服务器返回一个 http 响应

  经过前面的 6 个步骤,服务器收到了我们的请求,也处理我们的请求,到这一步,它会把它的处理结果返回,也就是返回一个 http 响应。

  http 响应与 http 请求类似,http 响应也由三部分构成,分别是:

  •   状态行
  •   响应头(Response Header)
  •   响应正文

  HTTP/1.1 200 OK

  Date: Sat, 31 Dec 2005 23:59:59 GMT

  Content-Type: text/html;charset=ISO-8859-1

  Content-Length: 122

  
  <html>

    <head>

      <title>http</title>

    </head>

    <body>

      <!-- body goes here -->

    </body>

  </html>

  状态行:

  状态行由协议版本,数字形式的状态码,以及响应的状态描述,各元素之间用空格分隔

  响应头:

  响应头部:由关键字 / 值对组成,每行一对,关键字和值用英文符号 " : " 分隔。

  响应正文:

  包含着我们需要的一些具体信息,比如 cookie,html,image,后端返回的请求数据等,这里需要注意,响应正文和响应头之间由一行空行,表示响应头的信息到空行为止。

8.浏览器显示 HTML

  在浏览器没有完整接收 html 文档时,他就已经开始显示这个页面了,浏览器是如何把页面呈现在屏幕上的呢?不同浏览器解析的过程可能不太一样,在这里我只介绍 webkit 的渲染过程,这个过程包括:

  解析 html 以构建 DOM 树  --> 构建 render 树 --> 布局 render 树 --> 绘制 render 树

  浏览器在解析 html 文件时,会 " 自上而下 "加载,并在加载过程中进行解析渲染,在解析过程中,如果遇到外部请求资源时,如图片,外链的 css ,iconfont 等,请求过程是异步的,并不会影响 html 文档进行加载。

  解析过程中,浏览器首先会解析 html 文件构建 DOM 树,然后解析 css 文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上,这个过程比较复杂,涉及到两个概念:reflow(回流)和 repain(重绘)。

  DOM 节点中的各个元素都是一盒模型的形式存在,这些都需要浏览器去计算其位置和大小,这个过程称为 reflow(回流),当盒模型的大小,位置及其他属性,如颜色,字体等都确定下来之后,浏览器便开始绘制内容,这个过程称为 repain(重绘)。

  页面在首次加载时必然会经历 reflow 和 repain ,reflow 和 repain 的过程是非常消耗性能的,尤其是在移动设备上,它会破坏用户体验,有时会造成卡顿,所以我们应该尽可能少的减少 reflow 和 repain。

  当文档加载过程中遇到js文件,html文档会挂起渲染(加载解析渲染同步)的线程,不仅要等待文档中js文件加载完毕,还要等待解析执行完毕,才可以恢复html文档的渲染线程。因为JS有可能会修改DOM,最为经典的document.write,这意味着,在JS执行完成前,后续所有资源的下载可能是没有必要的,这是js阻塞后续资源下载的根本原因。所以我明平时的代码中,js是放在html文档末尾的。

  JS的解析是由浏览器中的JS解析引擎完成的,比如谷歌的是V8。JS是单线程运行,也就是说,在同一个时间内只能做一件事,所有的任务都需要排队,前一个任务结束,后一个任务才能开始。但是又存在某些任务比较耗时,如IO读写等,所以需要一种机制可以先执行排在后面的任务,这就是:同步任务(synchronous)和异步任务(asynchronous)。

  JS的执行机制就可以看做是一个主线程加上一个任务队列(task queue)。同步任务就是放在主线程上执行的任务,异步任务是放在任务队列中的任务。所有的同步任务在主线程上执行,形成一个执行栈;异步任务有了运行结果就会在任务队列中放置一个事件;脚本运行时先依次运行执行栈,然后会从任务队列里提取事件,运行任务队列中的任务,这个过程是不断重复的,所以又叫做事件循环(Event loop)。

9.浏览器发送请求获取嵌入在 HTML 中的资源(如图片,音频,视频,css,js等等)  

  其实这个步骤可以并列在步骤8中,在浏览器显示HTML时,它会注意到需要获取其他地址内容的标签。这时,浏览器会发送一个获取请求来重新获得这些文件。比如我要获取外图片,CSS,JS文件等,类似于下面的链接:

  图片:http://static.ak.fbcdn.net/rsrc.php/z12E0/hash/8q2anwu7.gif

  CSS式样表:http://static.ak.fbcdn.net/rsrc.php/z448Z/hash/2plh8s4n.css

  JavaScript 文件:http://static.ak.fbcdn.net/rsrc.php/zEMOA/hash/c8yzb6ub.js

  这些地址都要经历一个和HTML读取类似的过程。所以浏览器会在DNS中查找这些域名,发送请求,重定向等等...

  不像动态页面,静态文件会允许浏览器对其进行缓存。有的文件可能会不需要与服务器通讯,而从缓存中直接读取,或者可以放到CDN中

每周分享之 二 http协议(3)的更多相关文章

  1. 每周分享之 二 http协议(1)

    本次分享http协议,共分为三部分,这是第一部分,主要讲解http的发展历程,各个版本,以及各个版本的特点. 一:http/0.9 最早版本是1991年发布的0.9版.该版本极其简单,只有一个命令GE ...

  2. 每周分享之 二 http协议(2)

    本次分享http协议,共分为三部分,这是第二部分,主要讲解请求与响应的字段,以及状态码. 以http/1.1版本的一个完整的请求与响应作为例子 http请求信息由三部分组成 1.请求方法(GET/PO ...

  3. 每周分享五个 PyCharm 使用技巧(二)

    这是 「PyCharm 技巧分享」系列的第二篇分享.由于上一篇文章得到了大家的一些赞同,所以今天又来给大家推荐一些我平时自己有用的小技巧,大家择需所取即可. 先声明下,并不保证对所有的人都是有帮助的, ...

  4. 关于启用 HTTPS 的一些经验分享(二)

    转载: 关于启用 HTTPS 的一些经验分享(二) 几天前,一位朋友问我:都说推荐用 Qualys SSL Labs 这个工具测试 SSL 安全性,为什么有些安全实力很强的大厂家评分也很低?我认为这个 ...

  5. 每周分享五个 PyCharm 使用技巧(一)

    PyCharm 是大多数 Python 开发者的首选 IDE,每天我们都在上面敲着熟悉的代码,写出一个又一个奇妙的功能. 一个每天都在使用的工具,如果能掌握一些高效的使用技巧,肯定会给我们的开发效率带 ...

  6. 每周分享五个 PyCharm 使用技巧(六)

    大家好,今天我又来给大家更新 PyCharm 的使用技巧. 从今年3月24号开始一直到今天,将近四个月的时间.包括本篇,一共更新了6篇文章,每篇 5 个小技巧,总计 30 个. 这30个使用技巧,全部 ...

  7. 每周分享五个 PyCharm 使用技巧(四)

    文章首发于 微信公众号:Python编程时光 PyCharm 是大多数 Python 开发者的首选 IDE,每天我们都在上面敲着熟悉的代码,写出一个又一个奇妙的功能. 一个每天都在使用的工具,如果能掌 ...

  8. 每周分享五个 PyCharm 使用技巧(三)

    文章首发于 微信公众号:Python编程时光 PyCharm 是大多数 Python 开发者的首选 IDE,每天我们都在上面敲着熟悉的代码,写出一个又一个奇妙的功能. 一个每天都在使用的工具,如果能掌 ...

  9. .net之工作流工程展示及代码分享(二)工作流引擎

    在介绍完表单类的时候,接下来介绍工作流引擎,主要由四个类组成,分别是流程.流程步骤.流程实例.流程步骤实例类. 流程类: [Serializable] public class Flow { [Xml ...

随机推荐

  1. java TreeSet 应用

    本文主要是介绍一下java集合中的比较重要的Set接口下的可实现类TreeSet TreeSet类,底层用二叉树的数据结构 * 集合中以有序的方式插入和抽取元素. * 添加到TreeSet中的元素必须 ...

  2. 即时通信系统Openfire分析之四:消息路由

    两个人的孤独 两个人的孤独,大抵是,你每发出去一句话,都要经由无数网络.由几百个计算机处理后,出在他的面前,而他就在你不远处. 连接管理之后 Openfire使用MINA网络框架,并设置Connect ...

  3. java继承和多态举例

    public class Test1 { public static void main(String[] args) { System.out.println(new Dog().name);//狗 ...

  4. 【javascript】谈谈HTML5 ——HTML兽进化, H5兽!

    作为一名Web开发者,可能你并没有对这个“H5”这个字眼投入太多的关注,但实际上它早已不知不觉进入到你的开发中,并且总有一天会让你不得不正视它,了解它并运用它   打个比方:<海贼王>中的 ...

  5. spring mvc:事务引起的try/catch失效

    在测试一个接口时,发现一个奇怪的现象:该接口使用@ResponseBody注解返回json格式数据,并且使用try/catch包括全部逻辑代码,debug后发现返回数据没有任何错误,只包含一段因产生异 ...

  6. Spring AOP 通过order来指定顺序

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt398 Spring中的事务是通过aop来实现的,当我们自己写aop拦截的时候 ...

  7. [译] 反思 1 号进程 / Rethinking PID 1

    By Lennart Poettering 译 SReadFox 原文链接:http://0pointer.de/blog/projects/systemd.html 译注:笔者大约在 2011 年读 ...

  8. windows 下 Mutex和Critical Section 区别和使用

    Mutex和Critical Section都是主要用于限制多线程(Multithread)对全局或共享的变量.对象或内存空间的访问.下面是其主要的异同点(不同的地方用黑色表示). Mutex Cri ...

  9. 【集美大学1411_助教博客】团队作业2——需求分析&原型设计 成绩

    首先要向各位同学道歉,最近助教的工作较多,并且伴随着频繁的出差,评论博客和评分都不及时,以致于同学们都没有得到反馈,在此我要表示歉意.其次,对于第二次团队作业,有两个团队没有提交到班级博客中但按时完成 ...

  10. 团队作业4——第一次项目冲刺(Alpha版本)4.26

    一.当天站立式会议照片 本次会议主要内容:汇报工作进度,根据完成情况调整进度,分配各自接口编写任务. 二.每个人的工作 三.燃尽图 横坐标:工作日,以天为单位,一共七天,代表着Alpha冲刺阶段的时间 ...