HTTP协议 作者:马育民 • 2017-12-25 19:56 • 阅读:10332 #### 什么是协议 参见:http://www.malaoshi.top/show_1EF2YFlxRxv3.html # 概述 HTTP全称是Hyper Text Transfer Protocol,翻译为:超文本传输协议 >它的发展是万维网协会(World Wide Web Consortium)和Internet工作小组IETF(Internet Engineering Task Force)合作的结果,(他们)最终发布了一系列的RFC,RFC 1945定义了HTTP/1.0版本。其中最著名的就是RFC 2616。RFC 2616定义了今天普遍使用的一个版本——HTTP 1.1。 HTTP协议是用于从 **WWW服务器** 传输 **超文本** 到本地 **浏览器** 的传送协议。 >它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。 # HTTP的请求响应模型 HTTP协议永远都是客户端发起请求,服务器响应。见下图:  也就是说:在客户端没有发起请求的时候,服务器无法将数据发送给客户端。 ### 在TCP/IP协议栈中的位置 HTTP协议处于OSI七层模型中的 **应用层** ,基于TCP/IP通信协议来传递数据,如下图所示:  默认HTTP的端口号为 **80** ### HTTPS HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer 或 Hypertext Transfer Protocol Secure,超文本传输 **安全协议**),是以 **安全** 为目标的HTTP通道,简单讲是HTTP的 **安全版**。 即HTTP下加入SSL层,如上图,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL HTTPS的端口号为 **443** # HTTP协议的主要特点: 1. **客户端** / **服务器** 模式。 >客户端可以是浏览器,也可以是爬虫,移动app 服务器是web服务器,如nginx、IIS、apache 2. 简单快速:客户端向服务器端 **请求** 时,只需传送 **请求方法** 和 **路径** 。 >请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。 3. 灵活:HTTP允许传输 **任意类型** 的数据。 >正在传输的类型由Content-Type加以标记。 4. **无连接**: **每次连接只处理一个请求**,服务器处理完客户的请求,并收到客户的应答后,即 **断开连接**。采用这种方式可以节省传输时间。 5. **无状态**:HTTP协议是无状态协议。无状态是指协议对于事务处理 **没有记忆能力**。 >缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。 > 举例: 相当于女朋友得了失忆症,每天女朋友醒来都不记得你是谁,为了让女朋友知道你是谁,就要将之前的经历告诉她,导致传送的数据量增大。 ### 一句话概括: http是客户端和服务器端,基于请求与响应模式的、无连接、无状态的、应用层的协议,基于TCP协议 # HTTP的请求响应模型 HTTP协议永远都是客户端发起请求,服务器响应。见下图:  也就是说:在客户端没有发起请求的时候,服务器无法将数据发送给客户端。 # 工作流程 一次HTTP的请求过程: 1. 域名解析,得到Web服务器的IP地址 >在浏览器地址栏输入www.baidu.com 敲回车后,将域名解析成IP地址 2. 浏览器向Web服务器发起TCP三次握手,建立连接 3. 浏览器向Web服务器 **发起http请求** 请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可能的内容。 4. Web服务器 **响应HTTP请求**,向浏览器发送html数据 5. 浏览器解析html代码,如果有js、css、图片等资源,就向Web服务器请求下载资源 >如果浏览器有keep-alive参数,是告知服务器要建立一个长连接,可以请求多个资源,下载资源的顺序就是按照代码里的顺序,浏览器会使用多线程 6. 浏览器对页面进行渲染呈现给用户,然后客户机与Web服务器断开连接。 7. Web服务器关闭TCP连接 如果在以上过程中的某一步出现错误,那么产生错误的信息将显示到浏览器上 **其中3、4是重点要学习的内容** # HTTP版本 HTTP协议经历了1.0、1.1、2.0版本,目前使用最广泛的就是 **HTTP1.1**, 特点如下: 1. **默认支持长连接** 由于HTTP协议基于TCP协议,TCP在建立连接时要有三次握手,如果没有长连接,那么每次请求都要重新建立TCP连接,都要三次握手,对性能有影响 2. 节约带宽 HTTP 1.1支持只发送header信息(不带任何body信息) 3. HOST域 web服务器可以设置虚拟站点,也即是说,web服务器上的多个虚拟站点可以共享同一个ip和端口。 # 浏览器向WEB服务器发请求 ### 类比 在男女处对象时,很多女生不说自己想要啥,当男生给的,不是自己想要的,就要闹别扭 浏览器相当于女生,WEB服务器相当于男生 在 **浏览器向WEB服务器** 发请求时,浏览器必须明确告诉WEB服务器,**我想要啥**,**我能接受啥**,这个就叫 **请求行** 和 **消息报头** 然后WEB服务器才能做出正确的回应,回应叫做 **响应** ### http请求 http请求由三部分组成,分别是: 1. 请求行 2. 消息报头 3. 请求正文 [](https://www.malaoshi.top/upload/0/0/1EF3uuwAw4y8.png) 如下面代码: ``` GET / HTTP/1.1\r\n Host: www.sohu.com\r\n Connection: close\r\n User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36\r\n Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n \r\n ``` ##### 注意: 最后一个```\r\n```表示全部数据发送完毕 ### 1、请求行 第一行是请求行,格式如下: ``` 请求方法+空格+URI+空格+协议版本+\r\n ``` GET是请求方法,下面会介绍其他请求方法 [URI](http://www.malaoshi.top/show_1EF2YGd7lGpR.html "URI") ,```/```表示根 最后是CRLF(回车和换行)```\r\n```结尾。(只有结尾是CRLF外) #### 请求方法 https://www.malaoshi.top/show_1EF6064tLPa2.html ### 2、消息报头 后面是消息报头,解释在后面 # 服务器端做出响应 在接收和解释请求消息后,服务器返回一个HTTP响应消息。 HTTP响应也是由三个部分组成,分别是: 1. 状态行 2. 消息报头 3. 响应正文,即html等 [](https://www.malaoshi.top/upload/0/0/1EF3uuwow5aB.png) 下面试 **状态行** 和 **消息报头**: ``` HTTP/1.1 200 OK Bdpagetype: 1 Bdqid: 0xacfbc5070001c483 Cache-Control: private Connection: Keep-Alive Content-Encoding: gzip Content-Type: text/html Cxy_all: baidu+46442892c785fac3cce0e176dcfa1275 Date: Fri, 04 Jan 2019 14:04:48 GMT Expires: Fri, 04 Jan 2019 14:04:44 GMT Server: BWS/1.1 Set-Cookie: delPer=0; path=/; domain=.baidu.com Set-Cookie: BDSVRTM=0; path=/ Set-Cookie: BD_HOME=0; path=/ Set-Cookie: H_PS_PSSID=26522_1467_27210_21107_28206_28131_28140; path=/; domain=.baidu.com Strict-Transport-Security: max-age=172800 Vary: Accept-Encoding X-Ua-Compatible: IE=Edge,chrome=1 Transfer-Encoding: chunked ``` ### 1、状态行 第一行是状态行,格式如下: ``` 协议版本+空格+状态码+空格+状态码文本描述+\r\n ``` ##### 状态码 https://www.malaoshi.top/show_1EF6064618w1.html ### 2、消息报头 后面是响应报头,解释在后面 ### 3、响应正文 服务器返回的资源的内容,如html、css、js等 # 消息报头 HTTP消息由客户端到服务器的请求和服务器到客户端的响应组成。请求消息和响应消息都是由开始行(对于请求消息,开始行就是请求行,对于响应消息,开始行就是状态行),消息报头(可选),空行(只有CRLF的行),消息正文(可选)组成。 HTTP消息报头包括普通报头、请求报头、响应报头、实体报头。 每一个报头域都是由名字+“:”+空格+值 组成,消息报头域的名字是大小写无关的。 ### 1、普通报头 在普通报头中,有少数报头域用于所有的 **请求** 和 **响应** 消息,但并不用于被传输的实体,只用于传输的消息。 1. **Cache-Control** 用于指定缓存指令,缓存指令是单向的(响应中出现的缓存指令在请求中未必会出现),且是独立的(一个消息的缓存指令不会影响另一个消息处理的缓存机制),HTTP1.0使用的类似的报头域为Pragma。 请求时的缓存指令包括:**no-cache**(用于指示请求或响应消息不能缓存)、no-store、**max-age**、max-stale、min-fresh、only-if-cached; 响应时的缓存指令包括: - public - private - **no-cache** - no-store - no-transform - must-revalidate - proxy-revalidate - **max-age** - s-maxage 2. **Date** 产生的日期和时间,一般用于响应消息 3. **Connection** 普通报头域允许发送指定连接的选项。 - **keep-alive** 表示长连接,可以请求多个资源 ### 2、请求报头 请求报头允许客户端向服务器端传递请求的附加信息以及客户端自身的信息。 **常用的请求报头** 1. **Accept** Accept请求报头域用于指定客户端接受哪些类型的信息。 2. Accept-Charset Accept-Charset请求报头域用于指定客户端接受的字符集。 3. **Accept-Encoding** Accept-Encoding请求报头域用于指定可接受的内容编码。 ``` Accept-Encoding:gzip.deflate 表示客户端支持gzip压缩,那么服务器发送的html内容是经过gzip压缩的 ``` 4. **Accept-Language** Accept-Language请求报头用于指定一种自然语言。 ``` Accept-Language:zh-cn. 表示客户端支持中文 ``` 6. Authorization Authorization请求报头域主要用于证明客户端有权查看某个资源。当浏览器访问一个页面时,如果收到服务器的响应代码为401(未授权),可以发送一个包含Authorization请求报头域的请求,要求服务器对其进行验证。 7. **Host**(发送请求时,该报头域是必需的) Host请求报头域主要用于指定被请求资源的Internet主机和端口号,它通常从HTTP URL中提取出来的 8. **User-Agent** 有时候,用电脑浏览器和手机浏览器访问同一个网页,显示效果是不一样的,服务器应用程序就是从User-Agent这个请求报头域中获取到这些信息。 User-Agent请求报头域允许客户端将它的操作系统、浏览器和其它属性告诉服务器。这个报头域不是必需的,但有的服务器为了 **反爬虫,会检验该报头**,如果没有不会发消息 ### 3、响应报头 响应报头允许服务器传递不能放在状态行中的附加响应信息,以及关于服务器的信息和对Request-URI所标识的资源进行下一步访问的信息。 **常用的响应报头** 1. Location Location响应报头域用于重定向接受者到一个新的位置。Location响应报头域常用在更换域名的时候。 2. **Server** Server响应报头域包含了服务器用来处理请求的软件信息。与User-Agent请求报头域是相对应的。下面是 ### 4、实体报头 请求和响应消息都可以传送一个实体(如HTML、JS、CSS、图片等)。一个实体由实体报头域和实体正文组成,但并不是说实体报头域和实体正文要在一起发送,可以只发送实体报头域。实体报头定义了关于实体正文(eg:有无实体正文)和请求所标识的资源的元信息。 **常用的实体报头** 1. **Content-Encoding** Content-Encoding实体报头域被用作媒体类型的修饰符,它的值指示了已经被应用到实体正文的附加内容的编码,因而要获得Content-Type报头域中所引用的媒体类型,必须采用相应的解码机制。Content-Encoding这样用于记录文档的压缩方法,如:```Content-Encoding:gzip``` 2. Content-Language Content-Language实体报头域描述了资源所用的自然语言。没有设置该域则认为实体内容将提供给所有的语言阅读者。 3. **Content-Length** Content-Length实体报头域用于指明实体正文的长度,以字节方式存储的十进制数字来表示。 4. **Content-Type** Content-Type实体报头域指明发送实体的类型 5. Last-Modified Last-Modified实体报头域用于指示资源的最后修改日期和时间。 4. **Expires** Expires实体报头域给出响应过期的日期和时间。为了让代理服务器或浏览器在一段时间以后更新缓存中(再次访问曾访问过的页面时,直接从缓存中加载,缩短响应时间和降低服务器负载)的页面,我们可以使用Expires实体报头域指定页面过期的时间。 例子:Expires:Thu,15 Sep 2006 16:23:12 GMT HTTP1.1的客户端和缓存必须将其他非法的日期格式(包括0)看作已经过期。 例子:为了让浏览器不要缓存页面,我们也可以利用Expires实体报头域,设置为0 5. **Transfer-Encoding** HTTP协议1.1版本的报头。表示采用分块编码,实体是分块来传输。 1. 在头部加入 Transfer-Encoding: chunked 之后,就代表这个报文采用了分块编码。这时,报文中的实体需要改为用一系列分块来传输。 2. 每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的 CRLF(\r\n),也不包括分块数据结尾的 CRLF。 3. 最后一个分块长度值必须为 0,对应的分块数据没有内容,表示实体结束。 ``` HTTP/1.1 200 OK Content-Type: text/plain Transfer-Encoding: chunked 25\r\n This is the data in the first chunk\r\n 1C\r\n and this is the second one\r\n 3\r\n con\r\n 8\r\n sequence\r\n 0\r\n \r\n ``` Content-Encoding 和 Transfer-Encoding 二者经常会结合来用,通过 Transfer-Encoding 分块,再进行 Content-Encoding压缩。 感谢以下帖子: https://www.cnblogs.com/wangning528/p/6388464.html https://www.cnblogs.com/li0803/archive/2008/11/03/1324746.html 原文出处:http://www.malaoshi.top/show_1EFIyjQT04v.html