30 个版本
0.8.1 | 2024 年 7 月 22 日 |
---|---|
0.7.9 | 2024 年 5 月 30 日 |
0.7.2 | 2024 年 3 月 13 日 |
0.6.8 | 2023 年 11 月 22 日 |
0.5.4 | 2021 年 11 月 29 日 |
#14 in #ietf
1,801 个星标 & 38 个关注者
740KB
16K SLoC
HTTP/3 协议
此软件包实现了 RFC9114。
实现依赖于
- neqo-transport —— 实现 QUIC 协议 (RFC9000) 和
- neqo-qpack —— 实现 QPACK (RFC9204);
功能
实现了客户端和服务器端的 HTTP/3 协议,尽管服务器端实现不适合用于生产,其主要目的是为了便于测试客户端代码。
WebTransport
(草案版本 2) 支持,并且可以使用 Http3Parameters
启用。
与应用程序的交互
驱动 HTTP/3 会话
此软件包不会创建操作系统级别的 UDP 套接字,它生成,即编码,应该作为 UDP 数据包有效载荷发送的数据,并消耗从 UDP 套接字接收的数据。例如,可以使用 std::net::UdpSocket
或 mio::net::UdpSocket
创建 UDP 套接字。
应用程序负责创建套接字,轮询套接字,并从套接字发送和接收数据。
除了接收数据外,HTTP/3会话的操作还可能在一定时间后触发,例如,在一段时间后,数据可能被视为丢失并需要重新传输,包速度控制需要计时器等。实现不使用计时器,而是当处理需要触发时通知应用程序。
驱动HTTP/3会话的核心功能是
- 在客户端 :
process_output
用于生成UDP有效载荷。如果没有生成有效载荷,此函数将返回回调时间,例如process_output
应再次调用的时间。process_input
用于消耗UDP有效载荷。process
将这两个函数合并为一个,即当有UDP有效载荷可用时消耗它,并生成一些要发送的UDP有效载荷,或者返回一个回调时间。- 在服务器端 只提供
process
。
与套接字的示例交互
let socket = match UdpSocket::bind(local_addr) {
Err(e) => {
eprintln!("Unable to bind UDP socket: {}", e);
}
Ok(s) => s,
};
let mut client = Http3Client::new(...);
...
// process_output can return 3 values, data to be sent, time duration when process_output should
// be called, and None when Http3Client is done.
match client.process_output(Instant::now()) {
Output::Datagram(dgram) => {
// Send dgram on a socket.
socket.send_to(&dgram[..], dgram.destination())
}
Output::Callback(duration) => {
// the client is idle for “duration”, set read timeout on the socket to this value and
// poll the socket for reading in the meantime.
socket.set_read_timeout(Some(duration)).unwrap();
}
Output::None => {
// client is done.
}
};
...
// Reading new data coming for the network.
match socket.recv_from(&mut buf[..]) {
Ok((sz, remote)) => {
let d = Datagram::new(remote, *local_addr, &buf[..sz]);
client.process_input(d, Instant::now());
}
Err(err) => {
eprintln!("UDP error: {}", err);
}
}
HTTP/3会话事件
Http3Client
和 Http3Server
生成事件,可以通过调用 next_event
获取。事件类型分别为 Http3ClientEvent
和 Http3ServerEvent
。它们在连接状态改变时、在流上接收到新数据时等通知应用程序。
...
while let Some(event) = client.next_event() {
match event {
Http3ClientEvent::DataReadable { stream_id } => {
println!("New data available on stream {}", stream_id);
}
Http3ClientEvent::StateChange(Http3State::Connected) => {
println!("Http3 session is in state Connected now");
}
_ => {
println!("Unhandled event {:?}", event);
}
}
}
依赖项
~4.5MB
~106K SLoC