深入理解 HTTP 协议

这篇文章是对学习 HTTP 协议的一个总结,之前花了一个多小时把《图解 HTTP》看了一遍,最近抽空有看了看,书上的知识有些陈旧,而且只适合入门,于是又在网上浏览了 HTTP 协议标准文档,看完之后觉得之前记忆的又被打散了,还是总结一下吧。最近时间比较紧,这篇文章会在站在协议高层总结一下不会涉及那么多细节,对于学习先掌握整体比较好,细节真正用到的时候再研究也不晚。

下面是一些 HTTP 学习资料。

HTTP 学习资源

文章:

HTTP

HTTP(Hypertext transfer Protocol),是一个轻量级、无状态的应用层协议,HTTP 在 Web 是用的最多,用来传参 HTML、音视频等多媒体文件,在分布式系统中也常用 HTTP 作为系统间交流传输数据的协议。

无状态 是指 HTTP 服务端对请求没有记忆能力。

HTTP 版本差异

对于目前比较流行的还是 HTTP/1.1,是大多数系统默认的 HTTP 协议版本。

HTTP/1.0 被设计出来不久 HTTP/1.1 就诞生了,1.1 是对 1.0 的完善,其最大的变化就是长连接。

在 1.0 的规范文档中只说明了连接可以经过多个中间者(代理、网关等),在 1.1 规范文档中详细说明了长连接,连接的发起以及如何断开连接的方式。

HTTP1.1

HTTP1.1 最大的特性是支持长连接(persistent connection),其一是允许客户端在在建立连接后发送多个请求,其次是 Pipeline ,允许客户端并发请求。

这些特性带来的好处:

  • 降低了建立和关闭 TCP 连接的时间,节省了路由和中间主机(客户端、服务的、代理、网关)计算资源
  • 使客户端同时发送 request
  • 减少了 TCP 传输的网络拥塞
  • 减少了 TCP 握手时间延迟

HTTP/2

HTTP/2 版本的特性主要为:

  1. 头部数据压缩(header fild compression)
  2. 二进制传输协议,传输数据格式的变化,以帧(frame)为单位传输数据,
  3. 长连接优化,服务端推送 Server Push

1.1 及以前,头部中的数据是文本,而且不同的请求又许多重复的字段,2.0 对头部压缩后可以提升传输效率,压缩方式有 Linux 的 gzip 和 Unix 的 compress。

使用协议而不是用文本的好处是:读取时更快速,扩展能力更强。

HTTP/1.1 的标志行和 header 都是文本(ASCII 码),而 HTTP/2 是二进制协议,头部和 body 都是二进制,并统称为帧 frame,帧包括头部帧和数据帧。

使用二进制协议,可以自定义额外的帧,HTTP/2 就额外定义了数十种帧,为将来的高级应用打下基础,这些协议如过用文本实现则会非常麻烦。

长连接方面,HTTP/2 也复用连接,客户端可以同时发送多个请求,服务端响应可以异步响应不同的请求而非之前请求和响应的顺序是一致的(避免了头部拥塞)。

服务端推送,服务端根据客户端请求的内容推测出之后的请求内容,主动向客户端推动资源,常见的是请求静态网页,web 服务器推测出相关的资源直接推送给浏览器。

Request、Resonse 格式

请求 Request

GET / HTTP/1.1
(CR+LF)
请求头 Header
(CR+LF)
请求体 Body

响应 Response

HTTP/1.1 200 OK
(CR+LF)
响应头 Header
(CR+LF)
响应体 Body

通信机制

HTTP Headers

头部字段分为:公用头部、请求响应私有头部、扩展头部

Status Code

状态码分为 5 类:

状态码 含义
1xx 协议操作类状态码,当收到此类响应状态码后代表后续还有操作
2xx 表示请求响应成功状态码,请求已经完成
3xx 重定向类状态码
4xx 客户端类异常状态码,服务端不会处理该类请求
5xx 服务端类异常状态码

1xx Informational

  • 100 continue,标识服务端已经接受请求还在处理,并没有拒绝
  • 101 switch protocol,协议升级,通常配合 Upgrade 头部使用,例如 http 升级 websocket

2xx Successful

  • 200 OK, 响应成功,GET、HEAD、POST 响应完成
  • 201 Created,服务端资源创建成功
  • 202 Accepted,服务端已经接受请求

3xx Redirection

  • 301 永久重定向,浏览器会改变用户收藏的标签
  • 302 要求客户端执行临时重定向
  • 303 对应当前请求的响应可以在另一个 URI 上被找到,当响应于 POST(或 PUT / DELETE)接收到响应时,客户端应该假定服务器已经收到数据,并且应该使用单独的 GET 消息发出重定向。

4xx Bad Request

  • 401 Unauthorized 未认证,用户未出具相应身份凭证
  • 403 Forbidden 服务拒绝资源访问
  • 404 资源未发现

5xx 服务端错误

  • 500 Internal Server Error 服务器内部错误
  • 501 Not Implemented 服务端不支持功能
  • 502 Bad Gateway 当一个 HTTP 服务器作为代理时,请求上层服务得到无效请求
  • 503 Service Unavailable 服务端维护或者过载,服务不可用
  • 504 Gateway Timeout 网关请求超时

HTTPS

HTTPS = HTTP + SSL/TLS

由于 HTTP 在网络上传输时明文,会导致数据泄露引起安全性问题。因此出现了 HTTPS,HTTPS 在传输过程中使用公私钥进行加密,SSL/TLS 在加密前需要协商传输公钥。

整个密钥传输到最终的加密 HTTP 通信过程是这样的:

先进行 TCP 链接(三次握手),然后进行 SSL/TLS 协商密钥(两次握手+一次公钥验证),验证无问题一个 HTTPS 连接就建立了。