HTTP 协议详解

788 阅读7分钟

本文是关于 HTTP 协议的学习笔记,这里做个总结与分享,有不足之处还望斧正~

网络分层

从主机 A 向主机 B 传输数据的过程中,可能会经历下图所示这些过程:

yuque_diagram.jpg 可以看出这是一个复杂的过程,于是就有了网络分层的概念,下面节选百度百科的部分解释:

网络分层就是将网络节点所要完成的数据的发送或转发、打包或拆包,控制信息的加载或拆出等工作,分别由不同的硬件和软件模块去完成。这样可以将往来通信和网络互连这一复杂的问题变得较为简单。

为了简化网络的复杂度,网络通信的不同方面被分解为多层次结构,每一层至只与紧挨着的上层或者下层进行交互,将网络分层,这样就可以修改甚至是替换某一层的软件,只要层与层之间的接口保持不变,就不会影响到其它层。

两种协议栈

网络层次可划分为两种网协议栈:

  • OSI
  • TCP/IP 协议簇

2021-06-21_102253.png

一个 http 请求的分层解析流程

当我们在浏览器地址栏输入一个想要访问的页面的域名,按下回车键后发生了哪些事呢?

浏览器是不认域名的,认的是 ip 地址,所以首先需要解析域名为 ip 地址,那么就看看是否缓存有对应域名的相关 DNS 信息,如果有就能直接获得 ip 地址。如果没有,就去本地 host 文件里找,如果也没有,就会发起一个 DNS 请求,获取服务器 ip 地址。

获取服务器 ip 地址的过程:

  1. 应用层构造一个 DNS 请求报文
  2. 调用传输层的 UDP 相关的协议,在 DNS 请求报文的基础上加一个 UDP 的请求头,交给网络层
  3. 网络层在 UDP 的请求报文基础上加一个 ip 的请求头,再把 ip 请求报文交给数据链路层
  4. 数据链路层会加上自己的 MAC 头和下一个机器的 MAC 地址,继续传给物理层,通常是传到路由器上面,路由器是一个三层的设备:
    (1). 通过物理层进行连接,之后把数据交给数据链路层
    (2). 链路层检查下 MAC 地址是不是给自己的,是就解析,不是就丢弃,解析完后,数据报文再往上传输给网络层
    (3). 网络层会去看下这个数据应该传到下一个路由器的地址是多少,然后通过运营商的网络接口传到运营商的路由器上面
    (4). 如果电脑配置的是运营商的 DNS 的话,就直接去运营商的 DNS 服务器上找对应的域名的 ip 地址,然后开始一层层原路返回

应用层拿到了 ip 地址后,就会进行 HTTP 请求报文的发送

  1. 调用传输层的 TCP 协议
  2. 调网络层的 ip 协议,加上 ip 头
  3. 调用数据链路层,加上 MAC 头
  4. 通过物理层和路由器进行数据的传输,这一次携带的是 ip 地址,所以不用访问运营商的 DNS 服务器,而是运营商根据 ip 地址把数据报文传输给目标服务器的运营商
  5. 在服务器的网络环境下,仍然逐层解析
  6. 物理层发往数据链路层
  7. 链路层判断数据是不是给自己的,是就进行解析,然后发往网络层
  8. 网络层判断 ip 地址是不是自己,是就进行解析,然后发往传输层
  9. 传输层解析 TCP 的端口比如80,把请求报文交给应用层应用程序
  10. 应用层解析报文,构造一个 HTTP 的响应报文,逐层返回给客户端

HTTP 协议

超文本传输协议(HTTP)是一种无状态的,以请求/应答方式运行的协议,它使用可扩展的语义和自描述消息格式,与基于网络的超文本信息系统灵活的互动。之所以说是无状态,下面有一段摘自知乎的解释:

因为 HTTP 的每个请求都是完全独立的,每个请求包含了处理这个请求所需的完整的数据,发送请求不涉及到状态变更。至于 HTTP/2,它应该算是一个有状态的协议了(有握手和 GOAWAY 消息,有类似于 TCP 的流控),所以以后说“HTTP 是无状态的协议”就不太对了,最好说“HTTP 1.x 是无状态的协议”

HTTP 报文形式

HTTP 协议的请求报文和响应报文的结构基本相同,由三大部分组成:

  • 起始行(start line)
    • 描述请求或响应的基本信息
    • 请求 GET /api/app/warehouseArea HTTP/1.1
    • 响应 HTTP/1.1 200 OK
  • 头部字段集合(header)
    • 使用 key-value 的形式更详细地说明报文,例如,Connection: Keep-Alive
    • 字段名不区分大小写,字段名里不能出现空格,可以使用连字符-,不能使用下划线_,字段名后面紧接冒号,不能有空格,而冒号后的字段值前可以有多个空格
    • 字段的顺序可任意排列
    • 字段原则上不能重复,除非这个字段本身语义允许,例如 Set-Cookie
  • 消息正文(entit)
    • 实际传输的数据,不一定是纯文本,可以是图片、视频等二进制数据

HTTP 请求的完整过程

yuque_diagram (2).jpg

TCP(传输控制协议)

面向连接的,可靠的,基于字节流的传输层通信协议。

特点

  • 基于连接的:数据传输前需要建立连接
  • 全双工的:双向传输
  • 字节流:不限制数据大小,打包成报文段,保证有序接收,重复报文自动丢弃
  • 流量缓冲:解决双方处理能力的不匹配
  • 可靠的传输服务:保证可达,丢包时通过重发机制实现可靠性
  • 拥塞控制:防止网络出现恶性拥塞

TCP 连接管理

TCP 连接:四元组[源地址,源端口,目的地址,目的端口]
确立连接:TCP 三次握手

  • 所谓三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送 3 个包。
  • 同步通信双方初始序列号(ISN)
  • 协商 TCP 通信参数(MSS,窗口信息,指定校验和算法)

TCP 包

2021-06-11_170940 (1).png

如何进行握手(三次握手)

yuque_diagram.jpg
说明:

  • SYN_SENT 表示请求连接,当你要访问其它的计算机的服务时首先要发个同步信号给该端口,此时状态为SYN_SENT,如果连接成功了就变为 ESTABLISHED
  • "TCB" 是 "TCP (Transmission Control Protocol) Control Block" 的缩写,意思是 "TCP(传输控制协议)控制块"

TCP 四次挥手

yuque_diagram (1).jpg
A:发送 FIN 数据包,代表 A 不再发送数据
B:收到请求,开始应答,避免 A 重新发送 FIN
B:处理完数据后关闭连接,发送 FIN 请求
A:收到请求后发送 ACK 应答,B 服务可以释放连接

2MSL

MSL 是 Maximum Segment Lifetime 英文的缩写,中文可以译为“报文最大生存时间”,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
等待 2MSL 后释放连接,可以

  1. 防止报文丢失,导致 B 重复发送 FIN
  2. 防止滞留在网络中的报文对新建立的链接造成数据扰乱

HTTPS

由于 HTTP 天生“明文”的特点,整个传输过程完全透明,任何人都能在链路中截获、修改或者伪造请求/响应报文,数据不具有可信性。因此诞生了为安全而生的 HTTPS 协议。 使用 HTTPS 时,所有的 HTTP 请求和响应在发送到网络之前,都有进行加密。

yuque_diagram.jpg

One More Thing

上面有说道 HTTP 协议的请求报文和响应报文,请求头 header 参数字段名不能使用划线 _,但其实是是合法的、符合 HTTP 标准的,服务器默认禁止使用是因为 CGI 历史遗留问题:下划线和中划线都为会被映射为 CGI 系统变量名中的下划线,这样容易引起混淆。在 nginx 服务器中,通过设置 underscores_in_headers on 是可以在字段名中使用下划线的。

感谢.gif
点赞.png