图解HTTP、HTTP知识大全

HTTP

浏览器与服务器之间通信的应用层协议,建立在TCP之上,是一个请求-响应协议,用于客户端和服务端之间的通信。

访问网页的时候就会用到 HTTP、举个例子,当你想要访问一个网站时:

1、浏览器本身是一个客户端,当你输入 URL 的时候,首先浏览器会去请求 DNS 服务器,通过 DNS 获取相应的域名对应的 IP

2、通过 IP 地址找到 IP 对应的服务器后,要求建立 TCP 连接,等浏览器发送完 HTTP Request(请求)包后,服务器接收到请求包之后才开始处理请求包,服务器调用自身服务,返回 HTTP Response(响应)包

3、客户端收到来自服务器的响应后开始渲染这个 Response 包里的主体(body),等收到全部的内容随后断开与该服务器之间的 TCP 连接。

|

|

| ------------------------------------------------------------ |

HTTP请求包(请求报文)

一个 HTTP 请求由 3 部分组成:

bash 复制代码
请求行(Request Line) 包含方法(GET,POST等)、路径、协议版本  # GET /index.html HTTP/1.1
请求头(Headers)常见请求头:Host、User-Agent、Accept、Cookie、Authorization、Content-Type、Content-Length
// 空格
请求体(Body) 一般是JSON、表单、文件上传 

下面是一个示例:

bash 复制代码
GET /domains/example/ HTTP/1.1      # 请求行: 请求方法 请求 URI HTTP 协议/协议版本
Host:www.iana.org               # 服务端的主机名
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4          # 浏览器信息
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 # 客户端能接收的 mine
Accept-Encoding:gzip,deflate,sdch       #是否支持流压缩
Accept-Charset:UTF-8,*;q=0.5        #客户端字符编码集
# 空行,用于分割请求头和消息体
# 消息体,请求资源参数,例如 POST 传递的参数
username=johndoe&password=123456 # 表单信息示例 、键值对用 & 连接、键和值用 = 连接、特殊字符会被URL编码
# JSON信息示例
{
  "name": "John Doe",
  "email": "john@example.com",
  "age": 30
}

常见HTTP方法及其语义

方法 描述 是否安全 是否幂等 是否有请求体
GET 获取资源
POST 提交数据(新增)
PUT 更新资源(整体)
PATCH 部分更新资源
DELETE 删除资源
HEAD 获取资源元信息
OPTIONS 查看服务器支持哪些方法

"安全"表示不会修改服务器状态

"幂等"表示多次执行效果相同

GET 和 POST 的本质区别:

GET POST
数据位置 URL 之后、以 分割URL和数据,参数间以 & 相连 请求体 body中
数据大小 较小(浏览器对URL 长度限制) 较大(没限制)
语义安全 安全、幂等、用于读取资源 不安全、非幂等、用于创建/提交数据

上面的语义安全不是信息安全,相反GET提交数据,信息不安全。

比如一个登录页面,通过 GET 方式提交数据时,用户名和密码将出现在 URL 上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码。

HTTP响应包(响应报文)

响应也包含 3 部分:

bash 复制代码
状态行(Status Line)# HTTP/1.1 200 OK
响应头(Headers)常见响应头:、Content-Type、Content-Length、Cache-Control、Set-Cookie、Server
响应体(Body)一般是 HTML、JSON、图片、视频等

下面是一个示例:

bash 复制代码
HTTP/1.1 200 OK                     # 状态行
Server: nginx/1.0.8                 # 服务器使用的 WEB 软件名及版本
Date: Tue, 30 Oct 2012 04:14:25 GMT    # 发送时间
Content-Type: text/html             # 服务器发送信息的类型
Transfer-Encoding: chunked          # 表示发送 HTTP 包是分段发的
Connection: keep-alive              # 保持连接状态
Content-Length: 90                  # 主体内容长度
// 空行 用来分割消息头和主体
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"... // 消息体

状态码

状态码用来告诉 HTTP 客户端,HTTP 服务器是否产生了预期的 Response,常见的状态码有5类:

状态码 信息 含义
1XX 提示信息 表示请求已被成功接收,继续处理
2XX 成功 表示请求已被成功接收,理解,接受
3XX 重定向 要完成请求必须进行更进一步的处理
4XX 客户端错误 请求有语法错误或请求无法实现
5XX 服务器端错误 服务器未能实现合法的请求

常用状态码详解:

成功类

200 OK:请求成功

201 Created:资源已创建

204 No Content:成功但无内容返回

重定向类

301 Moved Permanently:永久重定向

302 Found:临时重定向

304 Not Modified:使用缓存,无需重新下载

客户端错误

400 Bad Request:请求参数错误

401 Unauthorized:未认证

403 Forbidden:权限不足

404 Not Found:资源不存在

429 Too Many Requests:请求太频繁

服务器错误

500 Internal Server Error:通用错误

502 Bad Gateway:网关错误(上游服务异常)

503 Service Unavailable:服务器过载或维护

504 Gateway Timeout:上游超时

HTTP连接管理

HTTP协议是无状态的面向连接的协议

HTTP/1.0中:默认短连接

也就是说对于发送过的请求和响应都不做持久化处理,每一次都认为是新的请求或响应,每个请求都要重新建立TCP。

但是后来这样就变得很不方便

HTTP/1.1及以后: 默认长连接(开启了 Keep-Alive)

一个TCP可复用多次,提升性能,与用户身份无关

简单地说,当一个网页打开完成后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的 TCP 连接。

Keep-Alive 不会永久保持连接,它有一个保持时间,可以在不同服务器软件(如 Apache)中设置这个时间。

HTTP管理用户状态

两种方式:Cookie + Session / Token → 用于"用户身份与状态管理"

mathematica 复制代码
┌──────────┐
│  Cookie  │ ← 浏览器存储小数据
└────┬─────┘
     │
     ├── 保存 session_id → 服务器取 Session(状态在服务器)
     │
     └── 保存 Token(JWT) → 服务器校验签名(状态在客户端)

Cookie:浏览器保留小数据并自动发送给服务器

Cookie 是存储在浏览器的小数据,例如:

  • session_id(用于服务器识别用户)
  • 登录状态
  • 业务信息

每次对同域名请求时,浏览器都会自动带上 Cookie。

Cookie 是 Session、Token 的传输载体之一,不是身份验证本身。

Session:服务器端存储的用户状态

Session 的核心:

  • 数据存服务器
  • 浏览器只保存一个 session_id(通常存在 Cookie 中)
  • 服务端根据 session_id 找用户数据

典型流程:

浏览器访问:

复制代码
Cookie: session_id=abc123

服务端查 session 表:

复制代码
session["abc123"] = {user_id: 1, login:true}

Token(如 JWT):客户端携带完整凭证

Token 的定位:

  • 数据存在客户端
  • 服务端不存用户状态(无状态认证)
  • 每次请求需要带上 Token(Authorization header)

如:

复制代码
Authorization: Bearer eyJhbGciOi...

HTTP连接管理和用户状态管理的协同使用

  1. 使用 TCP + keep-alive 建立连接(保持连接不断开)

  2. 发 HTTP 请求:"POST /login"

  3. 服务器验证用户名密码

  4. 登录成功后:

    • Session 方式 :返回 Set-Cookie: session_id=xxx
    • JWT Token 方式 :返回 authorization token
  5. 浏览器保留 Cookie / Token

  6. 下一次请求

    mathematica 复制代码
    ┌───────────────────────────┐
    │是否复用 TCP 连接 (keep-alive) ------ 性能优化,与身份无关
    └───────────────┬───────────────┘
                    ↓
           浏览器自动带上:
           Cookie: session_id=xxx
           或 Authorization: Bearer token
                    ↓
          服务器识别用户身份:
          Session:用 session_id 查服务器存储
          或Token:验证 Token 签名,直接解析身份

可以看到:

  • keep-alive 只是优化连接,不管你是谁
  • Cookie/Session/Token 管理你是谁

其它协议与HTTP的关系

|

|

| ------------------------------------------------------------ |

HTTP的缓存

目的:

提升性能,减少服务器压力,提升用户体验。

HTTP 缓存分为两类:

① 强制缓存(强缓存 / 本地缓存)

浏览器直接使用本地缓存,不与服务端通信、请求都不会发出去。

依赖两个Header : Cache-Control、Expires(已过时)

bash 复制代码
Cache-Control: max-age=3600, public

② 协商缓存(弱缓存 / 条件缓存)

浏览器会向服务器发送请求,但带上缓存验证信息:

  • If-Modified-Since
  • If-None-Match

服务器判断是否能用缓存:

  • 可以 → 返回 304 Not Modified,浏览器继续用本地缓存
  • 不可以 → 返回 200 + 新资源

依赖三组Header:

If-Modified-Since + Last-Modified(按时间判断)

If-None-Match + ETag(推荐,基于内容)

Cache-Control + ETag

bash 复制代码
# If-Modified-Since + Last-Modified(按时间判断)
# 服务器返回资源时带:
Last-Modified: Tue, 10 Jan 2025 10:00:00 GMT
# 下次请求If-Modified-Since: Tue, 10 Jan 2025 10:00:00 GMT浏览器带:
If-Modified-Since: Tue, 10 Jan 2025 10:00:00 GMT

服务器判断:
文件没有变化 → 返回 304
变化了 → 返回 200 + 新内容

缺点:
时间精度是秒,1 秒内多次修改无法识别
内容没变但时间变了,也会导致重复下载

# If-None-Match + ETag(推荐,基于内容)
# 服务器给资源计算一个 hash:
ETag: "abc123"
# 下次请求浏览器带:
If-None-Match: "abc123"

服务器判断:
hash 一致 → 304
不一致 → 200 + 新内容

优点:
精度高,不受时间影响
内容不变 hash 不变,最准确

# Cache-Control  + ETag
Cache-Control: no-cache # 不使用强缓存
ETag: "abc123" # 决定资源是否变化

HTTP 缓存整体决策流程图

mathematica 复制代码
            ┌──────────────┐
            │  强缓存可用? │ ← Cache-Control: max-age
            └───────┬──────┘
                    │是
                    ▼
          浏览器直接使用缓存(不发请求)
                    │否
                    ▼
            ┌──────────────┐
            │  协商缓存可用? │ ← If-None-Match / If-Modified-Since
            └───────┬──────┘
                    │是
                    ▼
            返回 304,用本地缓存
                    │否
                    ▼
            请求服务器 → 返回 200 新资源

HTTPS

HTTP 本身是不安全的:

  • 明文传输
  • 可能被窃听(抓包能看到内容)
  • 可能被篡改(中间人攻击 MITM)
  • 可能被伪装(假服务器)

为了解决这些问题,HTTP 加上了 TLS 加密层,于是变成 HTTPS。

HTTPS 解决三件事

  • 加密(数据不会被窃听)
  • 完整性(不会被篡改)
  • 认证(确认服务器是真的)

使用两种加密方式协作

  • 非对称加密(RSA/ECDHE):安全地交换密钥
  • 对称加密(AES):加密真正的数据

数字证书(CA)

服务器通过证书提供公钥、 浏览器用 CA 链验证证书是否可信、 防止假网站冒充

握手流程

  1. 客户端发起:支持的加密算法 + 随机数
  2. 服务器回证书 + 随机数
  3. 客户端生成 pre-master key,用公钥加密发给服务器
  4. 双方生成同一个对称密钥
  5. 之后所有 HTTP 都用这个对称密钥加密

总结:HTTPS 用证书验证服务器,用非对称加密交换密钥,再用对称加密安全传输 HTTP 数据。

相关推荐
q***071425 分钟前
Java实战:Spring Boot application.yml配置文件详解
java·网络·spring boot
老前端的功夫2 小时前
HTTP 协议演进深度解析:从 1.0 到 2.0 的性能革命
前端·网络·网络协议·http·前端框架
氵文大师2 小时前
A机通过 python -m http.server 下载B机的文件
linux·开发语言·python·http
LaoZhangGong1232 小时前
以太网HTTP数据包格式分析
c语言·stm32·网络协议·http·tcp·arp
赖small强3 小时前
【Linux 网络基础】libwebsockets 技术文档
linux·网络·https·tls·lib·websockets
TT哇3 小时前
消息推送机制——WebSocket
java·网络·websocket·网络协议
帧栈4 小时前
开发避坑指南(72):HttpHeaders 的add()方法和set()方法有什么区别?
java·spring·http
wadesir5 小时前
当前位置:首页 > 服务器技术 > 正文Linux网络HSRP协议(实现路由器热备份与高可用性的实用指南)
linux·服务器·网络
带土16 小时前
4. 两台win11 笔记本局域网内文件传输
网络