一文搞懂HTTP基础
# 1. HTTP是什么,有什么作用?
HTTP(Hyper Text Transfer Protocol)协议是网络通信数据传输的一种规约,如今,它无处不在,只要我们使用网络浏览消息,使用手机,我们便参与到其中使用它。随着互联网的发展,它也在适应变化升级,目前主流使用版本是HTPP/1.1,当然HTTP/2.0也在普及。
# 2. 网络基础
当然,学习认识HTTP不只是那么简单,要搞清楚它是如何被使用的,需要进一步了解网络基础,可靠的TCP/IP协议族。 互联网协议套件(英语:Internet Protocol Suite)是一个网络通信模型,以及一整个网络传输协议家族,为网际网络的基础通信架构,它常被通称为TCP/IP协议族,包括TCP(Transmission Control Protocol)和IP(Internet Protocol)。前者提供一种面向连接的、可靠的、基于字节流的传输层通信协议,后者属于协议族中网络层的协议,实现源主机与目标主机之间数据传输。
# 2.1. TCP/IP分层与OSI分层
涉及网络基础协议,那必须要了解OSI 7层分层概念模型,与TCP/IP 4层抽象模型。那为什么要分层呢?其实与我们软件开发一样,一份复杂庞大的系统都需要分层解耦,分层开发,各自做自己擅长的领域,便于各个层次之间尽可能的耦合;如我们场景的WEB应用开发三层架构:业务层、服务层,数据层,其实分层主要就是为了开发灵活。
- OSI 7层概念模型
层级划分 | 说明 |
---|---|
应用层 | 为应用软件提供相关接口协议,如HTTP、SMTP、SNMP、FTP、Telnet等等 |
表现层 | 负责把数据转换为能与接收者的系统格式兼容并适合传输的格式 |
会话层 | 负责计算机网络中两台计算机之间的通信连接维护 |
传输层 | 提供处于网络连接中的两台计算机之间的数据传输 |
网络层 | 用于处理网络中传输流动的数据包,也就是提供一条数据运输路线 |
数据链路层 | 负责网络寻址、错误侦测和改错,主要分为两个子层:LLC、MAC |
物理层 | 负责管理电脑通信设备和网络媒体之间的互通,在局域网上传输数据帧 |
- TCP/IP 4层概念模型
层级划分 | 说明 |
---|---|
应用层 | 提供各种通用的应用服务,如HTTP、FTP、DNS |
传输层 | 传输层对上层应用层, 提供处于网络连接中的两台计算机之间的数据传输,它支持相关协议如TCP、UDP、RTP、SCTP |
网络层 | 用于处理网络中传输流动的数据包,也就是提供一条数据运输路线 |
数据链路层 | 用于连接网络的硬件,如网卡、设备驱动、操作系统等等 |
# 2.2. TCP/IP传输基础
IP是属于网络层的网际协议,TCP是属于传输的可靠字节流传输协议,把传输数据分段以数据包的形式进行传输,送达目的地,为了能够实现可靠传输,采用三次握手与四次挥手的方式保证可靠。
- 3次握手
- 第1次握手(SYN=1,seq=x)客户端发送一个TCP的SYN标志位为1的包,指明客户端打算连接的服务器的端口,以及初始序号x,保存在包头的序列号seq字段里。发送完毕后,客户端进入SYN_SEND状态;
- 第2次握手(SYN=1,ACK=1,seq=y,ACK=x+1)服务器发回确认包ACK应答。即SYN标志位和ACK标志位均为1。服务器端选择自己ISN序列号,放到seq域里,同时将确认序号ack设置为客户的ISN加1,即x+1。发送完毕后,服务器端进入SYN_RCVD状态;
- 第3次握手(ACK=1,ACKnum=y+1)客户端再次发送确认包ACK,SYN标志位为0,ACK标志位为1,并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方,并且在数据段放写ISN发完毕后,客户端进入ESTABLISHED状态,当服务器端接收到这个包时,也进入ESTABLISHED状态,TCP握手结束。
- 4次挥手
- 第1次挥手(FIN=1,seq=x)客户端需要关闭连接,客户端发送一个FIN标志位置为1的包,表示自己已经没有数据可以发送了,但是仍然可以接受数据。发送完毕后,客户端进入FIN_WAIT_1状态;
- 第2次挥手(ACK=1,ACKnum=x+1)服务器端确认客户端的FIN包,发送一个确认包,表明自己接受到了客户端关闭连接的请求,但还没有准备好关闭连接。发送完毕后,服务器端进入CLOSE_WAIT状态,客户端接收到这个确认包之后,进入FIN_WAIT_2状态,等待服务器端关闭连接;
- 第3次挥手(FIN=1,seq=w)服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN置为1。发送完毕后,服务器端进入LAST_ACK状态,等待来自客户端的最后一个ACK。
- 第4次挥手(ACK=1,ACKnum=w+1)客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入TIME_WAIT状态,等待可能出现的要求重传的ACK包。服务器端接收到这个确认包之后,关闭连接,进入CLOSED状态。客户端等待了某个固定时间(两个最大段生命周期,2MSL,2Maximum SegmentLifetime)之后,没有收到服务器端的ACK,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入CLOSED状态。
# 2.3. TCP/IP数据包处理过程
当服务客户端向服务端发送请求,进行数据传输时,都会加工包装与解包;当客户端发起请求时,会根据每层协议进行包装,添加协议报文头,而服务端接收到数据后,反解析,根据Client发起请求协议中添加的标识,对数据报文层层拆包处理。
# 3. HTTP传输报文解析
我们每一次访问网络资源都会发起HTTP请求,通过浏览器控制台很容易看到请求中HTTP报文组成信息,HTTP协议就是通过一些定义的规范信息,实现客户端与服务端通信,识别传输的数据成功与否,如图发起https://urick.gitee.io/blog (opens new window)请求时的报文信息,通常我们通过浏览器查看时都是被浏览器格式化后的信息,HTTP报文应该只包含纯字文本信息和换行符的。
接下来详细说明阐述HTTP报文信息参数组成
- 请求首部字段(Request Header Fields)
请求头部属性主要包括客户端向服务端发送请求时通信的必要标识信息。
字段名 | 说明 |
---|---|
Accept | 用户代理可处理的媒体类型 |
Accept-Charset | 优先的字符集 |
Accept-Encoding | 优先的内容编码 |
Accept-Language | 优先的语言(自然语言) |
Authorization | Web认证信息 |
Expect | 期待服务器的特定行为 |
From | 用户的电子邮箱地址 |
Host | 请求资源所在服务器 |
If-Match | 比较实体标记(ETag) |
If-Modified-Since | 比较资源的更新时间 |
If-None-Match | 比较实体标记(与 If-Match 相反) |
If-Range | 资源未更新时发送实体 Byte 的范围请求 |
If-Unmodified-Since | 比较资源的更新时间(与If-Modified-Since相反) |
Max-Forwards | 最大传输逐跳数 |
Proxy-Authorization | 代理服务器要求客户端的认证信息 |
Range | 实体的字节范围请求 |
Referer | 对请求中 URI 的原始获取方 |
TE | 传输编码的优先级 |
User-Agent | HTTP 客户端程序的信息 |
- 通用首部字段(General Header Fields)
顾名思义,主要是在请求头部和响应头部信息都会出现的字段属性。
字段名 | 说明 |
---|---|
Cache-Control | 控制缓存的行为 |
Connection | 逐跳首部、 连接的管理 |
Date | 创建报文的日期时间 |
Pragma | 报文指令 |
Trailer | 报文末端的首部一览 |
Transfer-Encoding | 指定报文主体的传输编码方式 |
Upgrade | 升级为其他协议 |
Via | 代理服务器的相关信息 |
Warning | 错误通知 |
- 响应首部字段(Response Header Fields)
主要包括服务端响应客户端的必要通信标识信息。
字段名 | 说明 |
---|---|
Accept-Ranges | 是否接受字节范围请求 |
Age | 推算资源创建经过时间 |
ETag | 资源的匹配信息 |
Location | 令客户端重定向至指定URI |
Proxy-Authenticate | 代理服务器对客户端的认证信息 |
Retry-After | 对再次发起请求的时机要求 |
Server | HTTP服务器的安装信息 |
Vary | 代理服务器缓存的管理信息 |
WWW-Authenticate | 服务器对客户端的认证信息 |
- 实体首部字段( Entity Header Fields)
针对请求报文和响应报文的实体部分使用的首部,补充了资源内容更新时间以及与实体有关的数据信息。
字段名 | 说明 |
---|---|
Allow | 资源可支持的HTTP方法 |
Content-Encoding | 实体主体适用的编码方式 |
Content-Language | 实体主体的自然语言 |
Content-Length | 实体主体的大小(单位: 字节) |
Content-Location | 替代对应资源的URI |
Content-MD5 | 实体主体的报文摘要 |
Content-Range | 实体主体的位置范围 |
Content-Type | 实体主体的媒体类型 |
Expires | 实体主体过期的日期时间 |
Last-Modified | 资源的最后修改日期时间 |
在发起HTTP请求时,状态行中都会指定一个获取资源的Method,标识从服务端获取资源的动作,当前流行的RESTful设计规约就是合理有效的利用HTTP请求方法和响应状态码实现的,常见的方法有:
方法 | 功能 |
---|---|
GET | 通常用途获取服务资源信息 |
POST | 将请求体上送到服务器,传输数据比GET多 |
PUT | 更新服务资源 |
DELETE | 删除指定的资源 |
OPTION | 询问方法信息,那些信息时客户端可以支持的 |
PATCH | 用于对资源应用部分修改 |
# 4. HTTP状态码
状态码其实与我们开发中对接的错误码是一个原理,其实就是服务端与客户端的一个约定规则,服务端根据客户端的请求,完成业务处理逻辑,最后把处理结果告诉客户端,客户端则根据服务的状态码,提示用户,实现更友好的交互体验。通常HTTP主要分为以下几大类:
状态码类别 | 描述 |
---|---|
1XX | 信息类状态码,表示接收的请求正在处理 |
2XX | 成功类状态码,表示请求正常处理完毕 |
3XX | 重定向状态码,表示需要进行附加操作以完成请求 |
4XX | 客户端错误状态码,表示服务端无法处理请求(不符合服务端规范要求) |
5XX | 服务器错误状态码,表示服务端处理请求出错 |
开发中常用的状态码有:
状态码 | 描述 |
---|---|
200 | 表示服务端已正常处理了请求 |
204 | 服务端已正常处理请求了,没有内容需要更新 |
206 | 该状态码表示客户端进行了范围请求,服务端正常处理并在Content-Range中指定范围 |
400 | 表示请求报文格式不正确 |
403 | 请求被服务端拒绝,可能权限不足 |
500 | 服务端处理客户端请求时,自身内部逻辑出现错误 |
503 | 表示当前服务不可用,可能在维护 |
# 5. Cookie
由于HTTP是无状态的协议,通信结束后不会保存相关的信息,所以当我们需要使用上一个请求连接的信息来发起本次请求时,就无法满足需求,这时Cookie便诞生了,引用一个外部属性来保存HTTP的状态信息,也不会违背HTTP通信的准则,也满足了需求。
客户端会根据服务端响应头中Set-Cookie信息把cookie存储到本地,下一次请求的时候通过请求头字段Cookie携带给服务端,Cookie使用最多的就是用于用户的登录验证,比如前后端分离开发模式,也就是使用Cookie存储用户会话信息的。
如图其中Cookie信息主要包含Set-Cookie与Cookie两个字段,前者是服务端设置的信息,后者是客户端请求时携带的信息,其中Set-Coolie有一下几个属性:
NAME=VALUE:
Cookie数据,以key-value形式设置Expires=DATE:
Cookie的有效期(若不明确指定则默认为浏览器关闭前为止)Path=PATH:
将服务器上的文件目录作为Cookie的适用对象(若不指定则默认为文档所在的文件目录)Domain=DOMAIN:
域名白名单(若不指定则默认为创建 Cookie的服务器的域名)Secure:
表示只有在HTTPS认证通信才发送CookieHttpOnly:
限制Cookie不能够通过脚本读取
系统开发拓展阅读:究竟如何保证session一致性? (opens new window)
参考: