Http协议

前言

HTTP协议(超文本传输协议)最初的目的是为了提供一种发布和接收HTML页面的方法。通过HTTP协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。HTTP报文是面向数据报的,报文中的每一个字段都是一些ASCII码串,各个字段的长度是不确定的。作为一个应用层协议,Http是一个基于TCP/IP的短连接,无状态的协议。TCP协议来保证Http协议消息的可靠传送

TCP/IP(五层)四层网络模型

在计算机网络当中,国际组织OSI将其分为7层,从上到下依次是应用层,会话层,表示层,传输层,网络层,数据链路层,物理层它是一种开放式系统互联参考模型.这种七层模型比较复杂,所以之后的文章都围绕TCP/IP网络模型来展开说明

TCP/IP四层模型与OSI七层模型的区别
在TCP/IP网络模型中,会话层和表示层与应用层规整成了一个层,于是从上到下有如下五层:
应用层,传输层,网络层,数据链路层,物理层.
因为物理层属于比较底层的一层模型.他的工作牵扯到许多的硬件原理,和我们用Java处理应用相差较远.所以有时在TCP/IP模型当中不描述这一层. 即TCP/IP四层模型

TCP/IP模型各层基本职能

  • 物理层: 负责光/电信号的传递方式 . 例如现在以太网通用的网线(双绞线),光纤.以及现在wifi使用的电磁波等都属于物理层的概念. 物理层的能力决定了最大传输速率,传输距离,抗干扰性等.集线器就工作在这一层
  • 数据链路层: 负责设备之间的数据帧的传送和识别.交换机就工作在这一层
  • 网络层: 负责地址管理和路由选择.例如在IP协议中,通过ip地址来标志一台主机,并通过路由表的方式规划出两台主机之间的数据传输的线路(路由).路由器就在这一层,解决的是数据包转发的问题.解决的是广域网之间的通信问题
  • 传输层: 负责两台主机的数据传输任务.例如tcp,能够确保数据可靠的从源主发送到目标主机
  • 应用层: 负责应用程序间通信,网络编程主要就是针对这一层

URL

URL称作统一资源定位符 , 他唯一标识了一个网络资源在互联网中的位置.URL就是我们俗称的网址,通过url我们可以准确的找到想要访问的资源.
为什么要先说说URL呢,因为url可以帮助我们给一个特定的网络资源发送一个网络请求
举个栗子: 就像我们想要去找一个朋友,那么肯定要先知道他的家在哪里.此时这个url就相当于他家的地址,能够帮助我们找到我们想要找到的人
还有一个和URL 相似的标志符叫做URI(统一资源标识符),他们的区别简单来说就是: URI用某一字符串标识某一互联网资源,而URL表示资源的地址(互联网上所处的位置).可见URL是URI的子集

Http协议

之后打算从最上层到最下层依次介绍一下每一层的一些常见协议,首先就是应用层的Http协议(超文本传输协议)
在浏览器发送一个请求到目标服务器依靠的就是Http协议
Http协议是一种无状态的协议,具体表现为Http协议自身不对请求和响应之间的通信状态进行保存.也就是说在Http这个级别,协议对于发送过的请求和响应都不做持久化处理

Http协议格式

Http请求格式如下

image

一个Http请求一般由四部分组成:
请求行、请求头、空行、正文部分

请求行

请求行内容分为三部分 请求方法,请求路径,使用的协议及版本号
image

请求方法
常见的请求方法有GET,POST,PUT,HEAD,DELETE,OPTION等
每一种请求方法都有适合他应用的场景 .
例如在日常生活中使用浏览器访问一个网站或者资源,http请求一般都使用的是GET方法;而当要发起一个携带有参数的请求时往往使用的是POST方法.下面列出不同请求方法的使用场景

GET方法: 用来获取资源.对应请求资源的实体会作为响应返回.
POST方法: 用来传输实体的主体.向指定资源提交数据进行处理请求(提交表单,上传文件),有可能导致新的资源的创建或旧的资源的修改 > PUT方法: 一般用于传输文件
PUT方法: 传输文件.就像FTP协议的文件上传一样,要求在请求报文的主体中包含文件内容,然后保存到请求URI指定的位置
HEAD方法: 发送一个请求但是不返回请求的实体,只获得报文首部. 一般用来测试服务器的运行是否正常,也用来确认URI的有效性及资源更新的日期时间等.
DELETE方法: 按照请求URI删除指定页资源文件
OPTIONS方法: 用来查询针对请求URI指定的资源支持的方法
TRACE方法: 可以在使用代理上网的时候查看代理是否修改了自己的http请求
CONNECT方法: 要求用隧道协议连接代理.CONNECT方法要求在与代理服务器通信时建立隧道,实现用隧道协议进行TCP通信.主要使用SSL和TLS协议把通信内容加密后经网络隧道传输

前五个方法在HTTP/1.0和HTTP/1.1中都支持,后面的方法只有HTTP/1.1支持

具体的请求路径
用来标识请求资源在网络中的具体位置(目标资源的URL)

协议及版本号
指明此次所使用的协议是那个协议以及协议的版本号
在http 1.0中默认的连接方式是短连接,一次请求结束之后,客户端和服务端建立的连接就断开
在http 1.1中默认的连接方式是长连接,一次请求结束之后,客户端和服务端建立的连接不断开,下次请求仍然通过该已有的连接进行发送

请求头

请求头中包含了许多以key-value形式存储的字段.这些字段中包含了一些客户端对服务器端的额外需求.下面是一些常见的请求头的含义:

通用请求头(在请求和响应的报文里都会出现的请求头字段)

Connetion : 连接类型,客户端发送的报文首部中该字段为keep-alive时表示长连接.在http 1.1 中默认的就是长连接.当服务器想要明确指定断开连接的时候,在响应的请求头中会明确指定此字段为close (该字段还有一个作用是控制不再转发给代理的首部字段)
Cache-Control:no-cache : 用来控制使用缓存的请求头,客户端发送的请求中如果包含no-cache指令,则表示客户端不会接收缓存过的响应.于是,”中间”的缓存服务器必须把客户端请求转发给源服务器;如果服务器返回的响应中也包含no-cache指令,那么缓存服务器将不再对资源进行缓存.源服务器以后对于缓存服务器中提出的资源有效性不再进行确认,且禁止其对服务器响应进行缓存
date : 首部Date表明创建Http报文的时间和日期
pragma : 如果该字段指定no-cache,那么从发送请求的客户端开始一直到返回响应的服务器,整个过程中都不使用缓存.那么为什么不直接使用Cache-Control请求头呢.这是因为该请求头只在HTTP/1.1中适用.所有的转发器服务器并不能保证都使用的是HTTP/1.1.而pragma适用于1.1和1.0
via : 关于代理或者网关的请求头字段.当一个请求从客户端发送之后,没经过一个代理服务器,就会在该字段中添加当前代理服务器本身服务器的信息.

请求首部字段

请求首部字段是从客户端向服务器端发送请求报文中所使用的报文,他的主要作用在于告诉服务器端客户端的一些附加信息,客户端的信息,对响应内容的一些优先级设置等
Accept :用户代理可处理的媒体类型
Host : 请求的资源所处的互联网的主机名和端口号.此字段是唯一一个必须包含在请求头当中的 ;为什么要有该字段,因为一个ip地址可能对应着多个域名,当访问一个ip地址时,服务端很有可能并不知道这个请求到底是从哪发来的,所以就要使用该字段,明确说明请求的来源
User-Agent : 将创建请求的浏览器和用户代理名称等信息传达给服务器.记录了客户端程序的信息,包括使用的浏览器内核,版本,驱动等.
Accept-Encoding : 表示浏览器接收的字符编码
Accept-Language : 表示浏览器支持的语言,例如此例中,浏览器支持的语言分别是简体中文和中文,优先支持简体中文,zh-cn表示简体中文;zh 表示中文
Cookie : 客户机通过这个头告诉服务器,可以向服务器带数据,客户端和服务端也是通过这个请求头来交换cookie信息的
referer : 当前页面是从哪个页面跳转过来的
location : 搭配3xx状态码使用,告诉浏览器接下来去哪里,常用与重定向和请求转发
range : 对于只需获取部分资源的范围请求,包含首部字段Range即可告知服务器资源的指定范围
Content-length : 表示该次请求中实体数据的大小是多少.例如上例中空行后的body中数据共有36个字节,所有这个Content-length就为36
Content-type : 规定了客户端请求中有效载荷的媒体类型,当指定了字符编码则客户端和服务端都需要遵循此编码才能正确解读有效载荷中的内容
last-modify : 表示了服务端资源最后一次的修改时间

空行

空行上面的请求行和请求头合称为报文首部
空行的主要作用是用来告诉服务器请求的头部到此结束,下面的内容是请求的正文部分,例如post请求方法中的参数内容

有效载荷(报文主体)

请求中如果需要携带数据给服务器.则数据信息就存放在有效载荷中,也称为响应体.例如提交一个表单的时候表单数据就存放在响应体中

Http响应格式

image
响应报文也分为四部分,分别为:
响应行,响应头,空行,响应体

响应行

响应行中包括三部分

第一部分 : 使用的应用层协议及版本号,这个一般和请求的报文使用的都是同一协议

第二部分 : 响应状态码,状态码是用来反应服务端对客户端请求的响应情况的,大致分为5个状态,如下表
image
还有一些比较重要的单独列出:

  • 200 表明从客户端发送来的请求在服务器端被正常处理了
  • 204 表明服务器接收到的请求已成功处理,但在返回的响应报文中不包含实体的主体部分
  • 301/302 永久/临时重定向
  • 303 改状态码表示访问的资源存在着另外一个URI, 应使用GET方法定向获取请求的资源
  • 304(Not Modified) 未修改 –>这条状态码返回的信息是说 此时网页内容没有变动,此次的访问是从本地缓存进行的,而没有直接通过服务器(减轻了服务器的压力) 服务器告诉客户端,该网页没有被修改过,这时候客户端就知道去缓存中找了
  • 307 重定向中保持原有的请求数据:
    用处: 假如我们现在的请求方式是post,那么请求过来是携带着用户数据的,如果在第一次请求后又一次重定向行为,那么在重定向过后,请求中携带的数据是会丢失的,所以这时候应该使用状态码为307的重定向,这样就可以保留原有请求中的数据了
  • 400 4xx类型的响应结果表明客户端是发生错误的原因所在. 该状态码表示请求报文中出现了语法错误
  • 404 服务器无法找到请求的资源;除此之外,服务端有时不想接受请求且不想说明原因的时候也会返回此状态码
  • 500 该状态码表明服务器端在执行请求的时候发生了错误,也有可能是Web应用存在的bug或某些临时的故障
  • 503 表明服务器现在正处于超负荷或者维护的状态,暂时不能够处理请求

第三部分
状态文字,如果显示Ok,则代表响应正常完成

响应首部字段

响应首部字段是由服务器端向客户端返回响应报文中所使用的字段,用于补充响应的附加消息,服务器消息,以及对客户端的附加要求等信息
Accept-Ranges : 首部字段Accept-Ranges是用来告知客户端服务器是否能够处理范围请求,以指定获取服务器端某个部分的资源
age : 告诉客户端,源服务器在多久前创建了响应,单位值为秒
location : 常常和3xx配合用来进行重定向
retry-after : 告知客户端应该在多久之后再次发起请求.主要配合状态码503和3xx响应一起
server : 告知客户端当前服务器上安装的HTTP服务器应用程序信息.不单单会标出服务器上的软件应用名称,还有可能包括版本号和安装时日用的可选项
set-cookie : 开始状态管理所使用的Cookie信息

空行

分割响应头部和响应体,空行的下部就是响应报文的具体内容

响应体

响应体中包含了对请求报文的回复,有可能是一个html页面,也有可能是一个文件,音频等.响应体允许为空.如果响应体不为空,则在响应报文的响应头中会有一个Content-Length来说明响应体中响应内容的大小

以上就是Http请求报文和响应报文的基本内容,当浏览器给服务器发送一个http请求之后,服务器就会响应的返回一个http响应.数据的请求与传输的规则定义就是由Tttp协议规定的,Http协议是一个基于Tcp传输协议的应用层协议.是网络模型中最上层中的一个协议

Cookie

前面说了HTTP协议是一种无状态的协议,每当有一个新的请求发出后就会有一个新的响应产生,也就是说,无法根据之前的状态进行本次请求的处理.这种无状态的方式可以快速的处理大量事务,确保协议的可伸缩性,同时也使得HTTP协议十分简单.
但随着Web的不断发展,这种无状态的协议也带来了一些不便,例如用户登陆到一个商城,在他跳转到另外一个购物界面的时候,他需要的是能够继续保持登陆状态,但是由于是一个新的请求,所以此时兵并不能继续保存用户信息
为了解决这种情况,实现期望的保持状态功能,于是有了Cookie技术.有了Cookie再用HTTP协议通信,就可以保管状态了

使用Cookie的状态管理

Cookie技术通过在请求和响应报文中写入Coolie信息来控制客户端的状态
客户端会根据从服务端中发回的响应报文内的Set-Cookie的首部字段信息,通知客户端保存Cookie. 当下次客户端再往该服务器发送请求的时会在请求字段中携带上这个Cookie值
服务器端发现客户端发送过来的Cookie后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最终得到之前的状态信息

为Cookie服务的首部字段

当服务端开始准备管理客户端的状态的时,他会事先准备好各种信息,并使用set-cookie转告给客户端
Set-Cookie字段的部分属性
name=value : 赋予cookie的名称和其值(必须项)
expires = date : 指定cookie的有效期,到有效时期之后cookie失效,如果不设置该字段那么在浏览器关闭的时候cookie就会失效
secure: 用于限制web页面仅在HTTPS安全连接的时候,才可以发送cookie

首部字段cookie会告知服务器,当客户端想获得HTTP状态管理支持时,就会在请求中包含从服务器接收到的cookie.接收到多个cookie时,同样可以以多个cookie的形式发送

长连接(持久连接)

早期的HTTP协议只支持短链接,即一次请求,回应的过程后TCP连接就会断开.等到下一次的请求到来时便再次建立连接.这种方式对于文件量小的请求来说没有什么影响. 可随着HTTP的普及,文档中包含图片的情况越来越多.这也就意味着在访问包含图片的HTML页面时还会访问每一个图片资源.因此每一次的请求都会造成无谓的TCP连接建立和断开,增加通信量的开销
为了解决上述问题,HTTP/1.1和部分HTTP/1.0想出了持久连接的方法.持久连接的特点是: 只要任意一端没有明确提出断开连接,则保持TCP连接状态
长连接的好处:

  • 持久连接的好处在于减少了TCP连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载.
  • 减少开销的那部分时间,使得HTTP请求和响应能够更早的结束,这样Web页面的显示速度也就相应提高了
    在HTTP/1.1中,所有的连接默认的都是持久连接

什么是管线化

持久连接使得多数请求以管线化方式发送成为可能.从前发送请求后需要等待响应才能继续发送请求.管线化技术出现后,不用等待响应亦可直接发送下一个请求.
这样就能够做到同时并行发送多个请求,而不需要一个接一个的等待响应了

HTTP的缺点

  1. HTTP是不安全的传输协议,使用HTTP传输的内容在网络中全部以明文的形式传播,这样对于用户重要信息的保护是远远不够的,为了解决这样的问题,HTTP常常和SSL(安全套接层)组合使用,加密HTTP的通信内容
    在SSL建立安全通信线路之后,就可以在这条线路上进行HTTP通信了.与SSL组合使用的HTTP被称为HTTPS(超文本传输安全协议)
  2. 无法确定发送双方是否就是真正的通信对象,例如一个客户端对一个服务器端发送一个请求,这个请求很有可能被一个代理服务器拦截,实际请求等于并没有到真正想要请求的服务器;同理,服务器发送的响应也很有可能会被一个”冒牌”的客户端接收
    解决的方法就是: 使用SSL提供的 证书 ,证书由值得信赖的第三方机构颁布,用以证明服务器和客户端是实际存在的.另外,伪造证书从技术角度来说是异常困难的.所以只要能够确认通信双方持有的证书,即可判断通信双方的真实意图
  3. 中间人攻击(完整性问题)
    HTTP无法证明报文的完整性,也就是说在报文的传输过程中,内容可能已经遭到了篡改
    举个例子: 比如从某个Web网站上下载内容,是无法确定客户端下载的文件和服务器上存放的文件是否前后一致.文件内容在传输的过程中如果被修改了,作为客户端的我们也是不知道的
    解决方法: 还是配合SSL使用HTTP.SSL提供认证和加密处理及摘要功能.

    扩展

    HTTP+加密+认证+完整性保护 = HTTPS

    SSL的加密方式

    共享密钥加密: 加密和解密通用一个密钥的方式称为使用一把密钥的共享密钥加密,也被叫做对称密钥加密.使用这种方式的密钥缺点在于发送方在发送请求报文时需要把密钥也一同发送,那么就存在密钥在发送的过程中被截获的问题,也是不安全的.
    两把密钥的公开密钥加密: 这种公开密钥的方式采用两把非对称的密钥.一把叫做私有密钥,另一把叫做公开密钥.使用公开密钥加密方式,发送密文的一方使用对方的公开密钥进行加密处理,对方收到被加密的信息后,在使用自己的私有密钥进行解密.利用这种方式,不需要发送用来解密的私有密钥,也不必担心密钥被攻击者窃听
    SSL采用共享密钥加密和公开密钥加密混合的方式对报文进行加密
    在确保交换的密钥是安全的前提下,使用共享密钥加密方式进行通信
    否则
    使用公开密钥加密方式安全的交换稍后在共享密钥加密中所要使用的密钥
    可以使用由数字证书认证机构和其相关机关颁发的公开密钥证书来证明密钥本身的正确性