这是一个笔记博客

分类标签

当前:首页 > 超文本传送协议 (HTTP-Hypertext transfer protocol)

超文本传送协议 (HTTP-Hypertext transfer protocol)

2018-07-18 16:23    浏览量:0    作者

超文本传送协议 (HTTP-Hypertext transfer protocol) 定义了浏览器(即万维网客户进程)怎样向万维网服务器请求万维网文档,以及服务器怎样把文档传送给浏览器。从层次的角度看,HTTP是面向(transaction-oriented)应用层协议,它是万维网上能够可靠地交换文件(包括文本、声音、图像等各种多媒体文件)的重要基础。

一、从输入URL到页面加载完成的过程中都发生了什么事情? 
0.输入URL 
1.解析URL:把URL分割成几个部分:协议、网络地址、资源路径; 
2.浏览器查找域名的 IP 地址:如果URL合法,首先它会在DNS本地缓存表中查找,如果有则直接使用 hosts 文件里面的 ip 地址。如果没有则会向 dns 域名解析服务器发起域名解析请求,如果没有就会向它的上级服务器询问,如此递归查询找到对应的IP后,返回给浏览器。 
3 . 建立TCP连接:当获取IP之后,浏览器在传输层发起一条到达服务器的 tcp 连接,就开始与所请求的Tcp建立三次握手连接,连接建立后,就向服务器发出HTTP请求。 
4.构造并发送HTTP请求:一个典型的 http request header 一般需要包括请求的方法,例如 GET 或者 POST 等,之后浏览器发送了一空白行来通知服务器,它已经结束了该头信息的发送。 
5.服务器接受并处理HTTP报文 
6.服务器构造并发送响应报文 
7.浏览器接收报文,并开始构建页面 
8.关闭TCP连接:一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码 
Connection:keep-alive 
TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。 
9.开始根据资源的类型,将资源组织成屏幕上显示的图像,这个过程叫渲染,网页渲染是浏览器最复杂、最核心的功能。 
10.将渲染好的页面图像显示出来,并开始响应用户的操作。

处理网络响应与渲染。响应到达浏览器之后,浏览器首先判断状态码,如果是 200 开头的就好办,直接进入渲染流程,如果是 300 开头的就要去相应头里面找 location 域,根据这个 location 的指引,进行跳转,这里跳转需要开启一个跳转计数器,是为了避免两个或者多个页面之间形成的循环的跳转,当跳转次数过多之后,浏览器会报错,同时停止。如果是 400 开头或者 500 开头的状态码,浏览器也会给出一个错误页面; 
当浏览得到一个正确的 200 响应之后,先进行多国语言的编码解析;解决了字符集的问题,接下来就是构建 dom 树,再接着根据 dom 树和 css 样式表来构造 render 树, 这个才是真正的用于渲染到页面上的一个一个的矩形框的树,对于 render 树上每一个框,需要确定他的 x y 坐标,尺寸,边框,字体,形态,等等诸多方面的东西,render 树一旦构建完成,整个页面也就准备好了

需要说明的是,下载页面,构建 dom 树,构建 render 树这三个步骤,实际上并不是严格的先后顺序的,为了加快速度,提高效率,让用户不要等那么久,现在一般都并行的往前推进的,现代的浏览器都是一边下载,下载到了一点数据就开始构建 dom 树,也一边开始构建 render 树,构建了一点就显示一点出来,这样用户看起来就不用等待那么久了 
构建 dom 树的过程中,如果遇到了由 script 标签包起来的 js 动态脚本代码,那么会把代码送到 js 引擎里面去跑,如果遇到了 style 标签包围起来的 css 代码,也会保存下来,用于稍后的渲染。如果遇到了 img 等引用外部文件的标签,那么浏览器会根据指定的 url 再次发起一个新的 http 请求,去把这个文件拉取回来,值得一提的是,对于同一个域名下的下载过程来说,浏览器一般允许的并发请求是有限的,通常控制在两个左右,所以如果有很多的图片的话,一般出于优化的目的,都会把这些图片使用一台静态文件的服务器来保存起来,负责响应,从而减少主服务器的压力。

二、HTTP协议之URL 
http(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议,常基于TCP的连接方式 
http协议中规定了一个特殊规则:浏览器对一个服务器不能同时打开两个以上的连接(IP+Port)。这个规则应该是为了保护服务器不会很容易被洪水攻击。

1、HTTP URL的格式如下:http://host[":"port][abs_path] 
 http表示要通过HTTP协议来定位网络资源; 
 host表示合法的Internet主机域名或者IP地址; 
 port指定一个端口号,为空则使用缺省端口 80; 
 abs_path指定请求资源的URI;如果URL中没有给出abs_path,那么当它作为请求URI时,必须以“/”的形式给出,通常这个工作浏览器自动帮我们完成。 
DEMO:输入:www.sina.com.cn,浏览器自动转换成:http://www.sina.com.cn /

2、URL编码 
foo://example.com:8042/over/there?name=ferret#nose 
\_/ \___________________/ \__________/\___________/ \__/ 
scheme —— authority — path — query —fragment 


注意: 
Url参数字符串中使用key=value键值对这样的形式来传参 
Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、- _ . ~4个特殊字符以及所有保留字符。 
Url中只允许使用可打印字符。US-ASCII码中的10-7F字节全都表示控制字符,这些字符都不能直接出现在Url中。同时,对于80-FF字节(ISO-8859-1),由于已经超出了US-ACII定义的字节范围,因此也不可以放在Url中。

3、有一些字符(:/?#[]@)是用作分隔不同组件的。 
:冒号用于分隔协议和主机,/用于分隔主机和路径,?用于分隔路径和查询参数,等等。还有一些字符(!$&’()*+,;=)用于在每个组件中起到分隔作用的,如=用于表示查询参数中的键值对,&符号用于分隔查询多个键值对。当组件中的普通数据包含这些特殊字符时,需要对其进行编码。

RFC3986中指定了以下字符为保留字符:

! * ’ ( ) ; : @ & = + $ , / ? # [ ]

还有一些字符,当他们直接放在Url中的时候,可能会引起解析程序的歧义。这些字符被视为不安全字符,原因有很多。

 空格:Url在传输的过程,或者用户在排版的过程,或者文本处理程序在处理Url的过程,都有可能引入无关紧要的空格,或者将那些有意义的空格给去掉 
 引号以及<>:引号和尖括号通常用于在普通文本中起到分隔Url的作用 
 # :通常用于表示书签或者锚点 
 % :百分号本身用作对不安全字符进行编码时使用的特殊字符,因此本身需要编码 
 {}|\^[]`~:某一些网关或者传输代理会篡改这些字符

需要注意的是,对于Url中的合法字符,编码和不编码是等价的,但是对于上面提到的这些字符,如果不经过编码,那么它们有可能会造成Url语义的不同。因此对于Url而言,只有普通英文字符和数字,特殊字符$-_.+!*’()还有保留字符,才能出现在未经编码的Url之中。其他字符均需要经过编码之后才能出现在Url中。

4.如何对Url中的非法字符进行编码 
Url编码通常也被称为百分号编码:使用%百分号加上两位的字符——0123456789ABCDEF——代表一个字节的十六进制形式。Url编码默认使用的字符集是US-ASCII。例如a在US-ASCII码中对应的字节是0x61,那么Url编码之后得到的就是%61,我们在地址栏上输入http://g.cn/search?q=%61%62%63,实际上就等同于在google上搜索abc了。又如@符号在ASCII字符集中对应的字节为0x40,经过Url编码之后得到的是%40。 
这里写图片描述 
1) 对于非ASCII字符,需要使用ASCII字符集的超集进行编码得到相应的字节,然后对每个字节执行百分号编码。对于Unicode字符,RFC文档建议使用utf-8对其进行编码得到相应的字节,然后对每个字节执行百分号编码。如“中文”使用UTF-8字符集得到的字节为0xE4 0xB8 0xAD 0xE6 0x96 0x87,经过Url编码之后得到“%E4%B8%AD%E6%96%87”。 
2) 如果某个字节对应着ASCII字符集中的某个非保留字符,则此字节无需使用百分号表示。例如“Url编码”,使用UTF-8编码得到的字节是0x55 0x72 0x6C 0xE7 0xBC 0x96 0xE7 0xA0 0x81,由于前三个字节对应着ASCII中的非保留字符“Url”,因此这三个字节可以用非保留字符“Url”表示。最终的Url编码可以简化成“Url%E7%BC%96%E7%A0%81”,当然,如果你用”%55%72%6C%E7%BC%96%E7%A0%81”也是可以的。

Javascript中提供了3对函数用来对Url编码以得到合法的Url,它们分别是escape / unescape,encodeURI / decodeURI和encodeURIComponent / decodeURIComponent。

三、HTTP协议之请求

如果某项请求发送到您的服务器要求显示您网站上的某个网页(例如,用户通过浏览器访问您的网页或 Googlebot 抓取网页时),服务器将会返回 HTTP 状态码响应请求。 
此状态码提供关于请求状态的信息,告诉 Googlebot 关于您的网站和请求的网页的信息。 
一些常见的状态码为: 
200 – 服务器成功返回网页 
404 – 请求的网页不存在 
503 – 服务器超时 
下面提供 HTTP 状态码的完整列表。点击链接可了解详情。您也可以访问 HTTP 状态码上的 W3C 页获取更多信息。 
1xx(临时响应) 
表示临时响应并需要请求者继续执行操作的状态码。 
100(继续) 请求者应当继续提出请求。服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。 
101(切换协议) 请求者已要求服务器切换协议,服务器已确认并准备切换。 
2xx (成功) 
表示成功处理了请求的状态码。 
200(成功) 服务器已成功处理了请求。通常,这表示服务器提供了请求的网页。如果是对您的 robots.txt 文件显示此状态码,则表示 Googlebot 已成功检索到该文件。 
201(已创建) 请求成功并且服务器创建了新的资源。 
202(已接受) 服务器已接受请求,但尚未处理。 
203(非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。 
204(无内容) 服务器成功处理了请求,但没有返回任何内容。 
205(重置内容) 服务器成功处理了请求,但没有返回任何内容。与 204 响应不同,此响应要求请求者重置文档视图(例如,清除表单内容以输入新内容)。 
206(部分内容) 服务器成功处理了部分 GET 请求。 
3xx (重定向) 
要完成请求,需要进一步操作。通常,这些状态码用来重定向。Google 建议您在每次请求中使用重定向不要超过 5 次。您可以使用网站管理员工具查看一下 Googlebot 在抓取重定向网页时是否遇到问题。诊断下的网络抓取页列出了由于重定向错误导致 Googlebot 无法抓取的网址。 
300(多种选择) 针对请求,服务器可执行多种操作。服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。 
301(永久移动) 请求的网页已永久移动到新位置。服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。您应使用此代码告诉 Googlebot 某个网页或网站已永久移动到新位置。 
302(临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来响应以后的请求。此代码与响应 GET 和 HEAD 请求的 301 代码类似,会自动将请求者转到不同的位置,但您不应使用此代码来告诉 Googlebot 某个网页或网站已经移动,因为 Googlebot 会继续抓取原有位置并编制索引。 
303(查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。对于除 HEAD 之外的所有请求,服务器会自动转到其他位置。 
304(未修改) 
自从上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容。 
如果网页自请求者上次请求后再也没有更改过,您应将服务器配置为返回此响应(称为 If-Modified-Since HTTP 标头)。服务器可以告诉 Googlebot 自从上次抓取后网页没有变更,进而节省带宽和开销。

305(使用代理) 请求者只能使用代理访问请求的网页。如果服务器返回此响应,还表示请求者应使用代理。 
307(临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来响应以后的请求。此代码与响应 GET 和 HEAD 请求的 301 代码类似,会自动将请求者转到不同的位置,但您不应使用此代码来告诉 Googlebot 某个页面或网站已经移动,因为 Googlebot 会继续抓取原有位置并编制索引。 
4xx(请求错误) 
这些状态码表示请求可能出错,妨碍了服务器的处理。 
400(错误请求) 服务器不理解请求的语法。 
401(未授权) 请求要求身份验证。对于登录后请求的网页,服务器可能返回此响应。 
403(禁止) 服务器拒绝请求。如果您在 Googlebot 尝试抓取您网站上的有效网页时看到此状态码(您可以在 Google 网站管理员工具诊断下的网络抓取页面上看到此信息),可能是您的服务器或主机拒绝了 Googlebot 访问。 
404(未找到) 
服务器找不到请求的网页。例如,对于服务器上不存在的网页经常会返回此代码。 
如果您的网站上没有 robots.txt 文件,而您在 Google 网站管理员工具“诊断”标签的 robots.txt 页上看到此状态码,则这是正确的状态码。但是,如果您有 robots.txt 文件而又看到此状态码,则说明您的 robots.txt 文件可能命名错误或位于错误的位置(该文件应当位于顶级域,名为 robots.txt)。 
如果对于 Googlebot 抓取的网址看到此状态码(在”诊断”标签的 HTTP 错误页面上),则表示 Googlebot 跟随的可能是另一个页面的无效链接(是旧链接或输入有误的链接)。 
405(方法禁用) 禁用请求中指定的方法。 
406(不接受) 无法使用请求的内容特性响应请求的网页。 
407(需要代理授权) 此状态码与 401(未授权)类似,但指定请求者应当授权使用代理。如果服务器返回此响应,还表示请求者应当使用代理。 
408(请求超时) 服务器等候请求时发生超时。 
409(冲突) 服务器在完成请求时发生冲突。服务器必须在响应中包含有关冲突的信息。服务器在响应与前一个请求相冲突的 PUT 请求时可能会返回此代码,以及两个请求的差异列表。 
410(已删除) 如果请求的资源已永久删除,服务器就会返回此响应。该代码与 404(未找到)代码类似,但在资源以前存在而现在不存在的情况下,有时会用来替代 404 代码。如果资源已永久移动,您应使用 301 指定资源的新位置。 
411(需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。 
412(未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。 
413(请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。 
414(请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。 
415(不支持的媒体类型) 请求的格式不受请求页面的支持。 
416(请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态码。 
417(未满足期望值) 服务器未满足”期望”请求标头字段的要求。 
5xx(服务器错误) 
这些状态码表示服务器在处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求出错。 
500(服务器内部错误) 服务器遇到错误,无法完成请求。 
501(尚未实施) 服务器不具备完成请求的功能。例如,服务器无法识别请求方法时可能会返回此代码。 
502(错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。 
503(服务不可用) 服务器目前无法使用(由于超载或停机维护)。通常,这只是暂时状态。 
504(网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。 
505(HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。 
合理利用这些状态码,避免错误利用,必将会为你的网站带来更佳的浏览者体会,为你的网站发展,奠定坚实的发展基础。

推荐阅读