这里整理一下关于Http协议的学习笔记。html
注:文章中的部分图片来自于网络,侵删java
大学学过计算机网络课的都知道OSI模型,即计算机网络模型,OSI模型由7层组成,除了OSI模型还有网络协议栈(也称为TCP/IP模型),其表示以下图(图片来自网络)所示:linux
通常咱们都使用五层模型的概念,这里就以五层模型来总结一下各个层的功能。web
五层模型在实际中的通讯过程以下所示:面试
下面一图囊括了大部分的各层协议:chrome
在linux上的进程通讯学习文章中介绍了套接字的使用,主要用于进行远程进程之间的通讯,在计算机网络知识领域,套接做为进程与网络之间沟通的媒介提供了应用层与传输层连接的功能。在应用程序中咱们经过将在应用层封装好的报文交付于套接字使得网络进程之间能够进行相互的通讯。既然进行通讯,就要商量好对应的协议,应用层协议就定义了应用程序进程中如何进行传递报文的。数据库
应用层协议定义了以下的规则:浏览器
关于应用层协议能够查看RFC文档来了解对应详细规则。缓存
Http(超文本传输协议)是互联网上应用最为普遍的一种网络协议。全部的WWW文件都必须遵照这个标准。Http协议使用TCP协议做为传输层的支撑,保证了在传输过程当中的可靠性,可是,Http也是一个无状态的协议,即一个请求对应一次响应,服务器只响应客户端的请求,不记录任何状态信息,一秒内发送2次相同的请求,服务器就会响应2次。服务器
当使用TCP的时候,TCP提供了两种链接的方式:非持续性链接以及持续性链接(默认),区别在于每一个请求/响应是单独的一个TCP链接发送仍是全部的请求都由一个TCP链接发送。
Http报文分为两种:请求报文和响应报文。请求报文的结构以下:
首先查看一个简单的请求报文:
GET /dir/page.html HTTP/1.1 Host: www/baidu.com Connection: close User-Agent: Mozilla/5.0 Accept-language: fr
报文的第一行称之为请求行,后续的称之为首部行(请求头部)。请求行包含三个字段,分别是方法字段,URL字段以及Http版本字段。
关于方法字段,HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法。HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。下面是各个方法的意义(图片截图来自菜鸟教程):
Http中定义了大量的请求头部以及响应头部,详细的能够查看这篇文章,这里就不详细罗列出来了。从上面的图中还能够看到最后一行为请求数据(请求实体),请求实体在POST中会进行填充数据,如表单数据。
接下来看下响应报文,响应报文的结构与消息报文的结构一致,惟一不一样的是叫法,第一行为状态行,而后是响应行(状态行),响应头部,空行和响应正文。看下例子:
HTTP/1.1 200 OK Date: Mon, 27 Jul 2009 12:28:53 GMT Server: Apache Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT ETag: "34aa387-d-1568eb00" Accept-Ranges: bytes Content-Length: 51 Content-Type: text/plain
关于Http响应状态码介绍以下:
罗列一些例子以下:
在Http使用中,我以为须要注意的是两点,一个cookie的使用,另外一个是Http的缓存机制。下面对两方面的知识作个整理。
首先是cookie,上述也介绍了Http是一个无状态的,所以也简化了服务器的设计。然而从用户的角度而言,用户更倾向于保存在某个网站上保存必定的信息,如用户信息(chrome上会常常看到提示咱们是否保存用户信息),这时候cookie就应运而生了。HTTP Cookie(也叫Web Cookie或浏览器Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。一般,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登陆状态。Cookie使基于无状态的HTTP协议记录稳定的状态信息成为了可能。
一次完整的cookie使用记录以下,更详细的能够查阅这篇文章:
接下来就是Http缓存操做,首先自主思考一下若是咱们须要本身实现该怎么作呢?
既然咱们能想到,开发Http协议的人可能比咱们更厉害咯,下面总结一下这两种缓存方式对应Http的实现。
首先是Expires(对应第一种缓存状况)以及Pragma,Expires,Pragma都是Http1.0的产物,Pragma主要控制是否容许客户端缓存,若是服务器返回了:
Pragma: no-cache
那么就是告诉客户端禁止缓存,每次数据都从服务器去拿。Expires字段来自响应实体,服务器在返回数据时候能够加上当前字段来设置缓存时间,如底下返回数据:
Expires: Wed, 21 Oct 2015 07:28:00 GMT
Expires返回一个GMT标准时间,客户端获取以后存入数据库,在缓存时间内使用缓存,不然再次请求服务器。若是Expires,Pragma一块儿返回,Pragma的优先级高于Expires,即客户端不容许缓存。
响应报文中Expires所定义的缓存时间是相对服务器上的时间而言的,其定义的是资源“失效时刻”,若是客户端上的时间跟服务器上的时间不一致(特别是用户修改了本身电脑的系统时间),那缓存时间可能就没啥意义了。
接着介绍一下Cache-Control,Cache-Control在Http1.1中实现。Cache-Control的请求实体可选参数以下:
响应实体可选参数以下:
Cache-Control配合其余关键字能实现咱们上面说的任何一种缓存方式。这边咱们说的对应于响应实体Cache-Control,由于相对于客户端开发而言,客户端对于服务端的缓存策略控制相对叫弱。Cache-Control中经过max-age也实现了Expires的功能,不一样的是,max-age返回的是时间值,而不是明确的时间,如:
Cache-Control: max-age=36000
因为返回的是时间值,就能够趋避客户端时间与服务器时间相差较大的状况,从而解决了Expires的局限性。与Pragma对应的是no-store参数。
对比缓存实现主要有两种途径:Last-Modified/If-Modified-Since以及Etag/If-None-Match方式。
使用Last-Modified/If-Modified-Since方式的流程图以下:
Last-Modified主要回传的是对应文件服务器端最后修改的时间,客户端在第二次调用时将Last-Modified得到到的value存放在If-Modified-Since中从新传给服务端,服务端作数据比对,并返回对应的状态码给客户端,若是返回304,表明服务器数据未更新,直接使用客户端维护的缓存便可;更新了,返回200并带上数据发送给客户端。
经过Last-Modified也有必定的局限,若是一个文件更新了可是其内容本质上不变,那么服务器也会认为客户端须要进行更新数据,从而返回服务器认为更新后的,可是实际上没有更新的数据,这样形成了客户端从新得到一个如出一辙的文件。
因为Last-Modified的局限性,所以引入了Etag参数,Etag表明了文件的惟一标识码(如md5),Etag和If-None-Match一同使用,使用的流程以下图:
流程跟Last-Modified/If-Modified-Since一致。
总结一下相关关键字调用的优先级:
Pragma -> Cache-Control (max-age>Etag>Last-Modified)-> Expires
放上一张缓存流程图:
这里总结一下一题面试题吧,叙述一下在浏览器中输入http://www.baidu.com后发生的状况:
参考资料
<<计算机网络-自顶向下方法>>
http://www.cnblogs.com/Joans/p/3956490.html
http://www.javashuo.com/article/p-urqfeegv-ec.html