• 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2025-03-22 16:49 Aet 隐藏边栏 |   抢沙发  3 
文章评分 3 次,平均分 5.0

HTTP1

概述

HTTP/0.9局限性(1989

  1. 仅支持 GET 方法,无状态码、无头部字段,每次请求需重新建立 TCP 连接

HTTP/1.0性能瓶颈(1996

  1. 默认短连接导致频繁三次握手,且无复用机制,造成高延迟和资源浪费
  2. 关键需求:降低网络延迟、减少重复头部传输、支持复杂资源类型(如图片和脚本)

HTTP/1.1 革新(1997

  1. 引入 持久连接(Keep-Alive),默认复用 TCP 连接处理多个请求,并通过以下改进提升性能:
    1. 管道机制(Pipelining):允许客户端连续发送多个请求(实际因队头阻塞问题被禁用)
    2. 分块传输编码(Chunked Encoding):支持流式传输大文件
    3. 强制 Host 头部:支持虚拟主机托管

协议内容

请求报文结构

响应报文结构

关键头部字段

字段 作用
Host 指定目标服务器域名(HTTP/1.1 强制要求)
Connection keep-alive 表示保持连接,close 表示关闭
Content-Length 实体正文长度(单位:字节)
Content-Type MIME 类型(如 text/html; charset=utf-8
Cache-Control 控制缓存行为(如 max-age=3600

支持的方法

GET

  1. 作用
    1. 请求指定资源(如 HTML 页面、图片),参数通过 URL 传递(如 ?id=123
  2. 特点
    1. 安全(不修改资源)、幂等(多次请求结果一致)、可缓存
  3. 场景
    1. 加载网页、获取 API 数据

POST

  1. 作用
    1. 向服务器提交数据(如表单内容),请求体携带数据(如 JSON、文件)
  2. 特点
    1. 非安全(可能修改资源状态)、非幂等(重复提交可能产生不同结果)
  3. 场景
    1. 用户注册、文件上传

HEAD

  1. 作用
    1. GET 类似,但仅返回响应头(不包含实体正文)
  2. 特点
    1. 轻量级请求,用于检查资源是否存在或是否更新(如 Last-Modified 时间戳)
  3. 场景
    1. 验证链接有效性、资源缓存状态检查

PUT

  1. 作用
    1. 全量更新资源,客户端需提供完整数据
  2. 特点
    1. 幂等(多次更新结果一致),但可能覆盖其他用户修改
  3. 场景
    1. 用户信息全量更新

DELETE

  1. 作用
    1. 删除指定资源
  2. 特点
    1. 幂等(多次删除同一资源效果相同),但直接修改服务器状态
  3. 场景
    1. 删除文章、用户账户

OPTIONS

  1. 作用
    1. 查询服务器支持的请求方法或跨域权限(CORS 预检请求)
  2. 特点
    1. 用于 API 兼容性检查或安全策略验证
  3. 场景
    1. 跨域请求前的预检

TRACE

  1. 作用
    1. 回显客户端请求,用于调试网络路径
  2. 特点
    1. 因安全风险(如 XST 攻击)通常被禁用
  3. 场景
    1. 诊断代理服务器行为

CONNECT

  1. 作用
    1. 建立代理隧道(如 HTTPS 加密通信)
  2. 特点
    1. 由代理服务器处理,不直接暴露给业务层
  3. 场景
    1. 通过代理访问 HTTPS 网站

PATCH

  1. 扩展方法(非 HTTP/1.1 原生)
  2. 作用
    1. 局部更新资源(仅修改部分字段)
  3. 特点
    1. 非幂等(多次更新可能产生不同结果),需定义数据格式(如 JSON Patch
  4. 场景
    1. 修改用户昵称或部分配置

对比

  1. PUTPOST 的误用
    1. PUT 用于全量更新(客户端控制资源标识)
    2. POST 用于创建资源(服务器分配标识)

持久连接(Keep-Alive

概述

  1. HTTP/1.0 中,每次请求都需要建立新的 TCP 连接,导致 三次握手和四次挥手的频繁开销,尤其对于含多个资源(如 CSSJS、图片)的网页,加载性能极差
  2. 持久连接(Keep-Alive) 的提出正是为了复用 TCP 连接,允许 同一连接处理多个请求/响应,从而减少延迟和资源消耗

工作原理与协议定义

  1. HTTP/1.0:非默认支持,需显式通过头部协商:

  1. HTTP/1.1:默认开启持久连接,若需关闭需显式声明:

连接复用流程

  1. 客户端发送首个请求,建立 TCP 连接
  2. 服务端响应后,保持连接开放(而非关闭)
  3. 客户端在 同一连接 上发送后续请求,无需重复握手
  4. 连接空闲超时(如 Nginx 默认 75 秒)或达到最大请求数后关闭

TCP Keepalive 的区别

特性 HTTP Keep-Alive TCP Keepalive
作用层级 应用层(HTTP 协议) 传输层(TCP 协议)
目的 复用 TCP 连接处理多个 HTTP 请求 检测连接存活状态,防止半开连接
实现方式 通过 Connection 头部协商 内核参数控制(如 tcp_keepalive_time
触发条件 HTTP 请求完成后保持连接 连接空闲后发送心跳包
典型配置 Nginx 的 keepalive_timeout 75s; Linux 系统的 /proc/sys/net/ipv4/ 参数

实际配置示例(Nginx

相关库

cpp-httplib

  1. 单头文件库,支持同步客户端/服务端
  2. 适合快速原型开发
  3. 客户端示例代码:

  1. 服务端示例代码:

libcurl

  1. 多协议支持(HTTP/HTTPS/FTP),异步请求
  2. 适合高性能客户端

Boost.Beast

  1. 基于 Boost.Asio,支持 HTTP/WebSocket,高度可扩展
  2. 适合企业级服务端开发

HTTP1的问题与解决方案

核心瓶颈

  1. 队头阻塞(HOL Blocking
    1. 管道机制因响应顺序依赖导致性能下降
  2. 头部冗余
    1. 每次请求携带重复头部(如 User-Agent),浪费带宽
  3. 连接数限制
    1. 浏览器对同一域名限制并发连接数(通常 6-8 个),影响资源加载速度

优化方案

  1. 域名分片(Domain Sharding
    1. 将资源分散到多个子域名突破连接限制
  2. 资源合并
    1. 合并 CSS/JS 文件、使用雪碧图减少请求次数
  3. 协议演进
    1. 通过 SPDY 协议过渡到 HTTP/2,引入多路复用和头部压缩

HTTP/1.1 管道化(Pipelining)的瓶颈

  1. 问题
    1. 请求必须按顺序响应,队头阻塞(Head-of-Line Blocking)导致性能下降
  2. 解决方案
    1. 使用 HTTP/2 多路复用或 HTTP/3 QUIC 协议规避 TCP 层阻塞

HTTP2

概述

HTTP/1.1的瓶颈

  1. 队头阻塞
    1. 单个 TCP 连接中请求必须按顺序处理,前序请求延迟会阻塞后续请求,导致页面加载效率低下
  2. 头部冗余与低效
    1. 每次请求需重复传输 User-AgentCookie 等字段,浪费带宽(约 500-800 字节/请求)
  3. 连接数限制
    1. 浏览器对同一域名限制 6-8 个并发连接,资源加载需多次 TCP 握手(3-RTT
  4. 协议规范庞大
    1. RFC2616 长达 176 页,实现复杂且存在互操作性问题(如 HTTP 管道化未被广泛支持)

HTTP2的革新

  1. 核心目标
    1. 提升传输效率、降低延迟、支持现代 Web 应用需求(如实时通信、高并发资源加载)
  2. 技术基础
    1. 基于 GoogleSPDY 协议演进,通过二进制分帧、多路复用等机制重构协议层

协议内容

二进制分帧层

  1. 帧结构(9 字节头部 + 变长负载):
字段 长度 描述
Length 24 bits 负载长度(不含帧头)
Type 8 bits 帧类型(如 DATAHEADERSPRIORITY
Flags 8 bits 标志位(如 END_STREAM 表示流结束)
Stream ID 31 bits 流标识符(唯一标识逻辑通道)
  1. 流(Stream
    1. 逻辑双向通道,通过 Stream ID 区分不同请求/响应,支持并发传输
  2. 消息(Message):
    1. 由多个帧组成的完整 HTTP 请求或响应(如 HEADERS + DATA

多路复用

  1. 实现方式
    1. 单个 TCP 连接上并发传输多个流的帧,消除队头阻塞

  1. 优势
    1. 减少 TCP 连接数,提升带宽利用率(对比 HTTP/1.1 提升 40%+ 吞吐量)

头部压缩(HPACK

  1. HPACK算法
    1. 静态表:预定义 61 个高频头部字段(如 :method: GETcookie
    2. 动态表:按需更新,存储新出现的头部键值对(LRU 淘汰策略)
    3. 哈夫曼编码:对值进行压缩
  2. 压缩效果:
    1. 首次请求压缩率约 50%,后续请求可达 90%

服务器推送

  1. 机制
    1. 服务端主动推送客户端可能需要的资源(如 CSSJS),减少 RTT
  2. 实现示例(Nginx配置):

优先级与流量控制

  1. 优先级
    1. 通过 PRIORITY 帧指定流的依赖关系和权重(如视频流优先于图片)
  2. 流量控制
    1. 基于滑动窗口机制,防止接收端缓冲区溢出

支持的方法

概述

  1. HTTP/2 未引入新方法,完全兼容 HTTP/1.1 的语义,支持以下 9 种标准方法:
    1. GET
    2. POST
    3. HEAD
    4. PUT
    5. DELETE
    6. OPTIONS
    7. TRACE
    8. CONNECT
    9. PATCH
  2. 特性
    1. 所有方法通过二进制帧传输,支持多路复用和头部压缩
    2. 方法语义与 HTTP/1.1 完全一致,开发者无需修改业务逻辑

CONNECT方法的扩展

  1. HTTP/2CONNECT 方法进行了增强,支持 Extended CONNECT Protocol
  2. 用途
    1. 建立隧道以支持 WebSocket 或其他应用层协议
  3. 示例(Node.js):
    1. 服务端需启用 enableConnectProtocol 设置
    2. 客户端通过 :protocol 伪头部声明目标协议

方法优化与性能影响

  1. 多路复用优势
    1. 所有方法均可通过单 TCP 连接并发执行,消除 HTTP/1.1 的队头阻塞
    2. 示例:GET 请求加载页面时,同时发送 POST 提交数据,响应顺序可乱序返回
  2. 优先级控制
    1. 通过 PRIORITY 帧设置流依赖关系(如视频流优先于图片加载)
    2. 示例配置(Nginx):

相关库

nghttp2

  1. 专用 HTTP/2 实现,支持客户端/服务器/代理,提供底层 API 和工具链
  2. 客户端示例代码:

Boost.Beast

  1. 基于 Boost.Asio,支持 HTTP/WebSocket,适合高性能服务端开发

libcurl

  1. 多协议支持(含 HTTP/2),异步请求接口成熟

HTTP2核心改进与实现

多路复用

  1. 原理
    1. 通过单个 TCP 连接并行传输多个请求/响应,避免了 HTTP/1.1 的队头阻塞问题
  2. 示例(基于nghttp2库)

头部压缩

  1. 原理
    1. 通过静态表和动态表压缩重复的 HTTP 头部字段,减少冗余数据传输
  2. 示例
    1. HTTP 请求头 User-AgentCookie 在多次请求中仅需传输索引值

服务器推送

  1. 原理
    1. 服务器主动推送资源(如 CSSJS),减少客户端请求次数
  2. 示例代码

HTTP2的瓶颈与解决方案

TCP层队头阻塞

  1. 问题
    1. TCP 丢包会导致所有流阻塞(即使其他流的数据已到达)
  2. 解决方案
    1. HTTP/3 采用 QUIC 协议替代 TCPQUIC基于 UDP 实现多路复用与快速恢复

TLS握手延迟

  1. 问题
    1. TLS 1.21-RTT 握手,首次连接延迟较高
  2. 解决方案
    1. TLS 1.3 支持 0-RTTHTTP/3 QUIC 集成 TLS 1.3 减少握手开销

协议兼容性

  1. 挑战
    1. 旧设备/浏览器不支持 HTTP/2(如 IE11
  2. 策略
    1. 服务端降级为 HTTP/1.1CDN 动态适配协议版本

其他问题

TLS协议

  1. 概述
    1. TLSTransport Layer Security)是一种为网络通信提供 保密性、数据完整性 和 身份认证 的安全协议
    2. 其前身为 SSLSecure Sockets Layer),由网景公司于 1994 年首次提出,后由 IETF 标准化为 TLS
  2. 功能
    1. 加密通信:通过对称加密算法(如 AES)保护数据传输隐私
    2. 身份验证:基于数字证书(X.509)验证服务器或客户端身份
    3. 防篡改:利用哈希算法(如 SHA-256)生成消息认证码(MAC),确保数据未被篡改
  3. 发展历史
协议版本 发布时间 关键改进
SSL 1.0 未发布 存在严重安全漏洞,未公开使用
SSL 3.0 1996 引入对称加密和密钥交换机制,但因 POODLE 攻击等漏洞于 2014 年被弃用
TLS 1.0 1999 首个标准化版本,兼容 SSL 3.0,但存在降级攻击风险
TLS 1.2 2008 支持 SHA-256 等更强哈希算法,移除 MD5SHA-1 依赖
TLS 1.3 2018 简化握手流程(1-RTT)、移除不安全算法(如 RSA 密钥交换)、支持前向安全性(Forward Secrecy

TLS协议核心机制

  1. 协议分层
    1. TLS 记录协议:负责数据分块、压缩、加密和传输,封装上层协议(如 HTTP)的数据
    2. TLS 握手协议:协商加密算法、交换密钥、验证身份,建立安全会话
  2. 握手流程(以TLS 1.3为例)
    1. Client Hello:客户端发送支持的密码套件列表和随机数
    2. Server Hello:服务端选择密码套件并返回随机数及数字证书
    3. 密钥交换:客户端验证证书后,使用服务端公钥加密预主密钥(Pre-Master Secret
    4. 会话密钥生成:双方通过随机数和预主密钥生成对称加密密钥
  3. 密钥交换算法
    1. RSA:传统非对称加密(TLS 1.3 已弃用)
    2. Diffie-HellmanDH):支持前向安全性,如 ECDHE(基于椭圆曲线)

TLS关键特性与优势

  1. 前向安全性(Forward Secrecy
    1. 会话密钥独立于长期私钥,即使私钥泄露,历史通信仍安全(通过 ECDHE 实现)
  2. 会话恢复
    1. 通过 Session IDSession Ticket 复用先前协商的密钥,减少握手延迟
  3. 算法灵活性
    1. 支持多种密码套件(如 TLS_AES_128_GCM_SHA256),可动态适配安全需求

TLS场景

  1. HTTPS:保护网站数据传输(默认端口 443
  2. 电子邮件:加密 SMTPIMAPPOP3 协议(如 STARTTLS 扩展)
  3. 即时通信:保障聊天内容隐私(如 WhatsApp 的端到端加密基于 TLS
  4. 物联网(IoT):设备与云端的安全通信

关于握手流程1-RTT

  1. 概述
    1. 1-RTT1 Round Trip Time) 是指客户端与服务器在 仅一次网络往返 内完成 TLS 握手并建立加密通信的能力
    2. 这一特性在 TLS 1.3 中被正式引入,显著降低了握手延迟,提升了性能
  2. 对比TLS 1.2
    1. TLS 1.2 需要 2-RTT 完成完整握手
      Client HelloServer HelloKey ExchangeFinished
    2. TLS 1.3 通过合并消息和优化算法,将握手压缩至 1-RTT,同时支持 0-RTT(会话恢复场景)

TLS 1.31-RTT 握手流程如下:

  1. Client Hello
    1. 客户端发送以下关键信息:
    2. 支持的 TLS 版本(如 TLS 1.3
    3. 密码套件列表(优先选择前向安全的 ECDHE 算法)
    4. Client Random(客户端随机数)
    5. Key Share(客户端的椭圆曲线公钥参数,如 x25519

  1. Server Hello
    1. 服务器响应包含:
    2. 选定的 TLS 版本和密码套件(如 TLS_AES_128_GCM_SHA256
    3. Server Random(服务端随机数)
    4. Key Share(服务端的椭圆曲线公钥参数)
  2. 服务端完成握手
    1. 服务器在发送 Server Hello 后,直接附加以下消息:
    2. Encrypted Extensions(扩展参数)
    3. Certificate(服务器证书,可选)
    4. Certificate Verify(证书签名验证)
    5. Finished(加密的握手摘要,用于完整性校验)
  3. 客户端完成握手
    1. 客户端验证证书和签名后,发送:
    2. Finished(加密的握手摘要)
  4. 此时双方已具备加密能力,可立即开始应用数据传输

关于TLS密钥生成

  1. 客户端和服务端通过 ECDHE 算法 交换公钥
  2. 结合 Client RandomServer Random,生成 预主密钥(Pre-Master Secret
  3. 最终导出 主密钥(Master Secret) 用于对称加密通信

HTTP3

概述

HTTP2的局限性

  1. TCP 层队头阻塞
    1. 即使 HTTP/2 通过多路复用解决了应用层队头阻塞,但 TCP 的丢包重传机制会导致所有流阻塞(如单个丢包影响整个连接)
  2. 连接迁移问题
    1. TCP 连接依赖四元组(源 IP、端口,目标 IP、端口),网络切换时需重建连接,导致高延迟(如移动网络切换)
  3. TLS 握手开销
    1. TCP + TLS 1.21-RTT 握手,首次连接延迟较高
  4. 协议僵化
    1. TCP 实现位于操作系统内核,升级困难;QUIC 基于用户态,便于快速迭代

HTTP3的革新

  1. 核心目标
    1. 基于 QUIC 协议实现更低的延迟、更高的可靠性和安全性,适应现代网络环境(如移动网络、高丢包率场景)
  2. 技术基础
    1. QUICQuick UDP Internet Connections)基于 UDP,集成 TLS 1.3,提供 0-RTT 握手和独立流复用

协议内容

QUIC 协议核心机制

  1. 基于UDP
    1. 绕过 TCP 限制,减少内核依赖,支持用户态实现
  2. 多路复用与独立流
    1. 每个流(Stream)通过 Stream ID 唯一标识,丢包仅影响当前流

  1. 0-RTT握手
    1. 客户端缓存服务器配置(Server Config),首次连接 1-RTT,后续会话 0-RTT
  2. 连接迁移
    1. 通过 Connection ID 标识连接,IP/端口变更时无需重建连接

连接迁移

  1. 原理
    1. 通过连接 ID(而非 IP+端口)标识连接,支持网络切换(如 Wi-Fi→5G)不断线
  2. 场景
    1. 移动设备切换网络时,视频流传输无需重新建立连接

HTTP/3帧结构

  1. 帧类型:包括 DATAHEADERSPRIORITY 等,与 HTTP/2 类似但基于二进制格式
  2. 帧头字段(以 DATA 帧为例):
字段 长度 描述
Length 24 bits 负载长度(不含帧头)
Type 8 bits 帧类型(如 0x00 表示 DATA
Stream ID 62 bits 流标识符(最高位保留)

头部压缩(QPACK

  1. QPACK 算法:基于 HPACK 改进,支持乱序传输和动态表更新,避免 HTTP/2 的头部阻塞
  2. 编码示例:静态表预定义常用头部(如 :method: GET),动态表按需更新

优先级与流量控制

  1. 优先级帧(PRIORITY):
    1. 指定流的依赖关系和权重(如视频流优先)
  2. 流量控制
    1. 基于滑动窗口机制,防止接收端缓冲区溢出

支持的方法

概述

  1. HTTP/2 未引入新方法,完全兼容 HTTP/1.1 的语义,支持以下 9 种标准方法:
    1. GET
    2. POST
    3. HEAD
    4. PUT
    5. DELETE
    6. OPTIONS
    7. TRACE
    8. CONNECT
    9. PATCH

相关库

nghttp3

  1. 专用 HTTP/3 实现,支持客户端/服务器,底层依赖 QUIC 协议栈
  2. 客户端示例:

quiche

  1. Cloudflare 开源 QUIC 实现(Rust 编写,支持 C++ 绑定)

Boost.Beast

  1. 基于 Boost.Asio,实验性支持 HTTP/3

MsQuic

  1. 微软开源库,集成 Windows 网络栈,高性能 QUIC 实现

基于 QUIC 协议

  1. 原理
    1. 使用 UDP 替代 TCP,解决 TCP 的队头阻塞问题,支持 0-RTT 快速握手
  2. 示例代码(基于 quiche 库):
    1. 使用 quiche 库(Cloudflare 开源)实现 QUIC 连接

HTTP3的瓶颈与解决方案

协议兼容性

  1. 问题
    1. 旧设备/中间件(防火墙、路由器)可能不支持 UDP/QUIC,导致连接失败
  2. 解决方案
    1. 通过 Alt-Svc 头部协商协议(如 Alt-Svc: h3=":443"

0-RTT安全隐患

  1. 问题
    1. 0-RTT 数据可能遭受重放攻击
  2. 解决方案
    1. 服务端限制 0-RTT 数据为幂等操作,并采用 TLS 1.3 的防重放机制

UDP穿透能力

  1. 问题
    1. NAT 设备对 UDP 支持较差,导致丢包率上升
  2. 优化
    1. 使用前向纠错(FEC)和冗余数据包减少重传

性能调优

  1. 拥塞控制:QUIC 支持 BBRCubic 算法,需根据网络动态调整
  2. Nginx 配置示例:

HTTP/2HTTP/3对比

特性 HTTP/2 HTTP/3
传输层协议 TCP(存在队头阻塞) QUIC(基于 UDP,无队头阻塞)
握手延迟 1-RTT(TCP + TLS) 0-RTT(首次连接缓存密钥)
头部压缩算法 HPACK(依赖顺序传输) QPACK(支持乱序更新)
适用场景 稳定网络环境(如有线宽带) 高丢包/移动网络(如 5G、IoT)

记忆总结

HTTP1.1

核心特性

  1. 持久连接(Keep-Alive
    1. 默认复用 TCP 连接,减少重复握手开销,但同一连接中的请求需按顺序处理,存在 队头阻塞(Head-of-Line Blocking
  2. 管线化(Pipelining
    1. 允许客户端发送多个请求,但服务端必须按顺序响应,实际应用受限(如非幂等请求可能导致问题)
  3. 分块传输(Chunked Encoding
    1. 支持动态生成内容的分块传输,无需提前计算总大小
  4. 缓存优化
    1. 引入 Cache-ControlETag 等头部,支持更灵活的缓存策略
  5. Host
    1. 支持虚拟主机,允许同一 IP 托管多个域名

局限

  1. 队头阻塞严重(同一连接请求需顺序处理)
  2. 明文传输,安全性差
  3. 头部冗余,无压缩机制

HTTP2

核心改进

  1. 二进制协议
    1. 替代文本格式,提升解析效率,减少错误
  2. 多路复用(Multiplexing
    1. TCP 连接上并行处理多个请求/响应,解决应用层队头阻塞(但 TCP 层仍存在队头阻塞)
  3. 头部压缩(HPACK
    1. 减少重复头部传输,节省带宽(压缩率高达 90%
  4. 服务端推送(Server Push
    1. 主动推送关联资源(如 CSS/JS),减少客户端请求延迟
  5. 流优先级
    1. 按优先级传输资源(如优先加载 HTML 骨架)

局限

  1. 仍依赖 TCP,丢包时所有流被阻塞
  2. 需强制 TLS 加密(主流浏览器要求 HTTPS

HTTP3

核心改革

  1. 基于 QUIC 协议
    1. 底层改用 UDP,彻底解决 TCP 队头阻塞,每个流独立传输
  2. 0-RTT 握手
    1. 首次连接 1-RTT,后续会话 0-RTT(需缓存服务器配置)
  3. QPACK 头部压缩
    1. 针对 QUIC 优化的压缩算法,支持乱序传输
  4. 强制加密
    1. 集成 TLS 1.3,所有通信默认加密
  5. 连接迁移
    1. 网络切换(如 Wi-Fi → 5G)时保持连接,无需重建

优势场景

  1. 高丢包网络(如移动环境)
  2. 高频短连接(如 API 调用)
  3. 实时通信(如视频流、在线游戏)

对比表

特性 HTTP/1.1 HTTP/2 HTTP/3
底层协议 TCP TCP UDP(QUIC)
连接复用 持久连接(Keep-Alive) 多路复用 独立流复用
队头阻塞 应用层 & TCP 层 仅 TCP 层 完全解决
头部压缩 HPACK QPACK
加密强制 无(需手动 HTTPS) 主流强制 协议内建
握手延迟 高(3-RTT) 中(1-RTT) 低(0-RTT 恢复)
典型应用场景 传统 Web 页面 现代多资源网站 移动端、实时通信

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0 最后编辑于:2025-03-24
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享