cloudflare/quiche
摘要
quiche 是一个基于Rust的QUIC传输协议和HTTP/3的实现,提供用于处理QUIC数据包和管理连接的低级API。它被Cloudflare用于HTTP/3支持、Android的DNS解析器,并且可以集成到curl中。
查看缓存全文
缓存时间: 2026/09/19 14:50
cloudflare/quiche
来源: https://github.com/cloudflare/quiche
quiche crates.io (https://crates.io/crates/quiche)
docs.rs (https://docs.rs/quiche)
许可证 (https://opensource.org/licenses/BSD-2-Clause)
构建
quiche 是 IETF 规范的 QUIC 传输协议与 HTTP/3 的 Rust 实现。它提供了一个用于处理 QUIC 数据包和管理连接状态的底层 API。应用程序需要负责提供 I/O(例如 socket 处理)以及支持定时器的事件循环。更多关于 quiche 的由来及其设计思考,可以阅读 Cloudflare 博客中的一篇文章,其中包含更详细的说明。
谁在使用 quiche?
Cloudflare
quiche 为 Cloudflare 边缘网络的 HTTP/3 支持 提供支持。
可通过 cloudflare-quic.com (https://cloudflare-quic.com) 网站进行测试和实验。
Android
Android 的 DNS 解析器使用 quiche 来实现基于 HTTP/3 的 DNS。
curl
quiche 可集成到 curl中,为其提供 HTTP/3 支持。
快速入门
命令行应用
在深入 quiche API 之前,这里提供几个如何使用 quiche-apps crate 中提供的 quiche 工具的示例。这些工具不适用于生产环境;请参阅声明与注意事项。
按照构建部分提到的命令克隆项目后,可以这样运行客户端:
$ cargo run --bin quiche-client -- https://cloudflare-quic.com/
运行服务器的方式如下:
$ cargo run --bin quiche-server -- --cert apps/src/bin/cert.crt --key apps/src/bin/cert.key
(注意:提供的证书是自签名的,不应在生产环境中使用)
使用 --help 命令行标志可以获取每个工具选项的更详细描述。
配置连接
使用 quiche 建立 QUIC 连接的第一步是创建一个 Config 对象:
let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
config.set_application_protos(&[b"example-proto"]);
// 根据应用程序和用例的附加配置...
Config 对象控制着 QUIC 连接的重要方面,例如 QUIC 版本、ALPN ID、流控制、拥塞控制、空闲超时以及其他属性或功能。
QUIC 是一个通用的传输协议,其中有一些配置属性没有合理的默认值。例如,任何特定类型允许的并发流数量取决于在 QUIC 上运行的应用程序以及其他特定于用例的考虑。quiche 将多个属性默认设为零,应用程序很可能需要根据其需求使用以下方法将它们设置为其他值:
set_initial_max_streams_bidi()set_initial_max_streams_uni()set_initial_max_data()set_initial_max_stream_data_bidi_local()set_initial_max_stream_data_bidi_remote()set_initial_max_stream_data_uni()
Config 也包含 TLS 配置。可以通过现有对象的修改器来更改,或者手动构建一个 TLS 上下文,然后使用 with_boring_ssl_ctx_builder() 创建一个配置。一个配置对象可以被多个连接共享。
连接建立
在客户端,可以使用 connect() 工具函数创建新连接,而服务器端则使用 accept():
// 客户端连接
let conn = quiche::connect(Some(&server_name), &scid, local, peer, &mut config)?;
// 服务器端连接
let conn = quiche::accept(&scid, None, local, peer, &mut config)?;
处理传入数据包
使用连接的 recv() 方法,应用程序可以从网络上处理属于该连接的传入数据包:
let to = socket.local_addr().unwrap();
loop {
let (read, from) = socket.recv_from(&mut buf).unwrap();
let recv_info = quiche::RecvInfo { from, to };
let read = match conn.recv(&mut buf[..read], recv_info) {
Ok(v) => v,
Err(e) => {
// 发生错误,进行处理。
break;
},
};
}
生成传出数据包
传出数据包则使用连接的 send() 方法来生成:
loop {
let (write, send_info) = match conn.send(&mut out) {
Ok(v) => v,
Err(quiche::Error::Done) => {
// 写入完成。
break;
},
Err(e) => {
// 发生错误,进行处理。
break;
},
};
socket.send_to(&out[..write], &send_info.to).unwrap();
}
当数据包被发送后,应用程序负责维护一个定时器,以响应基于时间的连接事件。可以使用连接的 timeout() 方法获取定时器的到期时间。
let timeout = conn.timeout();
应用程序需要提供定时器实现,可以针对使用的操作系统或网络框架进行定制。当定时器到期时,应调用连接的 on_timeout() 方法,之后可能需要在网络上发送额外的数据包:
// 定时器到期,进行处理。
conn.on_timeout();
// 在超时后根据需要发送更多数据包。
loop {
let (write, send_info) = match conn.send(&mut out) {
Ok(v) => v,
Err(quiche::Error::Done) => {
// 写入完成。
break;
},
Err(e) => {
// 发生错误,进行处理。
break;
},
};
socket.send_to(&out[..write], &send_info.to).unwrap();
}
发送速率调整
建议应用程序对传出数据包的发送进行速率调整,以避免产生可能导致网络短期拥塞和丢包的数据包突发。
quiche 通过 send() 方法返回的 [SendInfo] 结构的 [at] 字段,为传出数据包提供了速率调整提示。该字段表示特定数据包应发送到网络的时间。应用程序可以使用平台特定的机制(例如 Linux 上的 SO_TXTIME 套接字选项)或自定义方法(例如使用用户空间定时器)来人为地延迟数据包发送,从而利用这些提示。
发送和接收流数据
经过一些往返交互后,连接将完成其握手,并准备好发送或接收应用数据。可以使用 stream_send() 方法在流上发送数据:
if conn.is_established() {
// 握手完成,在流0上发送一些数据。
conn.stream_send(0, b"hello", true)?;
}
应用程序可以使用连接的 readable() 方法检查是否有可读的流,该方法返回一个迭代器,包含所有有待读取数据的流。然后可以使用 stream_recv() 方法从可读流中获取应用数据:
if conn.is_established() {
// 遍历可读流。
for stream_id in conn.readable() {
// 流可读,读取直到没有数据。
while let Ok((read, fin)) = conn.stream_recv(stream_id, &mut buf) {
println!("在流 {} 上获取了 {} 字节", read, stream_id);
}
}
}
HTTP/3
quiche 的 HTTP/3 模块 提供了在 QUIC 传输协议之上发送和接收 HTTP 请求与响应的高层 API。
请查看 [quiche/examples/] 目录,获取关于如何使用 quiche API 的更完整示例,包括如何在 C/C++ 应用中使用 quiche 的示例(更多信息见下文)。
从 C/C++ 调用 quiche
quiche 在 Rust API 之上提供了一个轻量级 C API,可以更方便地将 quiche 集成到 C/C++ 应用(以及其他允许通过某种 FFI 形式调用 C API 的语言)中。
该 C API 遵循与 Rust API 相同的设计,仅受 C 语言本身约束的限制。当运行 cargo build 时,一个名为 libquiche.a 的静态库将与 Rust 库一起自动构建。这个库是完全独立的,可以直接链接到 C/C++ 应用中。
请注意,为了启用 FFI API,必须启用 ffi 特性(默认禁用),在运行 cargo 时传递 --features ffi 即可启用。
构建
quiche 需要 Rust 1.88 或更高版本来构建。可以使用 rustup (https://rustup.rs/) 安装最新的稳定版 Rust。
一旦 Rust 构建环境设置好,就可以使用 git 获取 quiche 源代码:
$ git clone https://github.com/cloudflare/quiche
然后使用 cargo 构建:
$ cargo build --examples
cargo 也可以用来运行测试套件:
$ cargo test
请注意,用于实现基于 TLS 的 QUIC 加密握手的 BoringSSL 需要构建并链接到 quiche。在使用 cargo 构建时,boring-sys crate 会自动完成此操作,但需要在构建过程中使用 cmake 命令。在 Windows 上还需要 NASM (https://www.nasm.us/)。官方 BoringSSL 文档 (https://github.com/google/boringssl/blob/master/BUILDING.md) 有更多细节。
或者,你可以通过设置 BORING_BSSL_PATH 环境变量来使用你自己的自定义 BoringSSL 构建:
$ BORING_BSSL_PATH="/path/to/boringssl" cargo build --examples
为 Android 构建
为 Android(NDK 版本 19 或更高,推荐 21)构建 quiche 可以使用 cargo-ndk(v2.0 或更高版本)。
首先需要安装 Android NDK,可以通过 Android Studio 或直接安装,并将 ANDROID_NDK_HOME 环境变量设置为 NDK 安装路径,例如:
$ export ANDROID_NDK_HOME=/usr/local/share/android-ndk
然后可以安装所需 Android 架构的 Rust 工具链:
$ rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
请注意,所有目标架构的最低 API 级别均为 21。还需要安装 cargo-ndk(v2.0 或更高版本):
$ cargo install cargo-ndk
最后,可以使用以下过程构建 quiche 库。请注意 -t <target> 和 -p <platform-level> 选项是必需的。
$ cargo ndk -t arm64-v8a -p 21 -- build --features ffi
更多信息请参阅 build_android_ndk19.sh。
为 iOS 构建
为 iOS 构建 quiche 需要以下条件:
- 安装 Xcode 命令行工具。可以通过 Xcode 或使用以下命令安装:
$ xcode-select --install - 安装 iOS 架构的 Rust 工具链:
$ rustup target add aarch64-apple-ios x86_64-apple-ios - 安装
cargo-lipo:$ cargo install cargo-lipo
要构建 libquiche,请运行以下命令:
$ cargo lipo --features ffi
或
$ cargo lipo --features ffi --release
iOS 构建在 Xcode 10.1 和 Xcode 11.2 上进行了测试。
构建 Docker 镜像
要构建 Docker 镜像,只需运行以下命令:
$ make docker-build
可以在以下 Docker Hub 仓库找到 quiche Docker 镜像:
- cloudflare/quiche (https://hub.docker.com/repository/docker/cloudflare/quiche)
- cloudflare/quiche-qns (https://hub.docker.com/repository/docker/cloudflare/quiche-qns)
latest 标签会在 quiche master 分支更新时更新。
cloudflare/quiche
提供安装在 /usr/local/bin 中的服务器和客户端。
cloudflare/quiche-qns
提供在 quic-interop-runner (https://github.com/marten-seemann/quic-interop-runner) 中测试 quiche 的脚本。
声明与注意事项
⚠️ 此仓库包含许多客户端和服务器示例应用程序,旨在演示 quiche 库 API 的简单用法。它们不适用于生产环境;不提供任何性能、安全或可靠性保证。
版权
版权所有 (C) 2018-2019, Cloudflare, Inc.
许可证请参阅 COPYING。
相似文章
@Ryrenz: 当信号降至一格时你仍能加载网页,这要感谢 quiche——Cloudflare 已完全…
Cloudflare 已将 quiche 开源,这是一个基于 Rust 实现的 QUIC 传输协议和 HTTP/3,用于其边缘网络,并被 Android 和 curl 采用以增强网络性能。
当“空闲”并不空闲:Linux 内核优化如何引发 QUIC 缺陷
Cloudflare 详细描述了其 QUIC 实现 quiche 中的一个缺陷,该缺陷由 Linux 内核针对 CUBIC 拥塞控制的优化引发,并导致了性能问题,同时介绍了相应的修复方案。
利用 QUIC 反向散射推断超大规模部署配置
研究人员通过网络望远镜收集的 QUIC 反向散射,推断 Google、Meta 与 Cloudflare 服务器的重传配置,在 QUIC 强调隐私的设计下仍能揭示部署细节。
@QingQ77: 用 Rust 写的高性能 IM 后端,走 QUIC 协议实时传消息,支持 P2P 打洞和群聊广播。 https://github.com/nicolastinger/only-talk-rs… 用 Actix-web 做 RESTful …
一个基于 Rust + Actix-web + QUIC 的高性能即时通讯后端,支持 P2P 打洞、群聊广播、多种存储后端,可单进程或分离部署。
Cloudflare 快速隧道
Cloudflare 快速隧道提供了一种免费且安全的方式,可以通过单条命令立即将本地应用部署到互联网,通过 Cloudflare 的全球网络提供自动 HTTPS 和 DDoS 防护。