Node.js v26.2.0 文档


QUIC#>

稳定性: 1.0 - 早期开发

源代码: lib/quic.js

'node:quic' 模块提供了 QUIC 协议的实现。要访问它,请使用 --experimental-quic 选项启动 Node.js,并执行以下操作:

🌐 The 'node:quic' module provides an implementation of the QUIC protocol. To access it, start Node.js with the --experimental-quic option and:

import quic from 'node:quic';const quic = require('node:quic');

该模块仅在 node: 方案下可用。

🌐 The module is only available under the node: scheme.

概述#>

🌐 Overview

quic 模块提供用于创建 QUIC 客户端和服务器的 API。

🌐 The quic module provides APIs for creating QUIC clients and servers.

相关的 RFC 和规范#>

🌐 Relevant RFCs and specifications

QUIC 和 HTTP/3 协议由一系列 RFC 定义,这些 RFC 主要由 IETF QUIC 工作组制定。强烈建议使用此模块的用户熟悉这些文档。

🌐 The QUIC and HTTP/3 protocols are defined by a collection of RFCs produced primarily by the IETF QUIC Working Group. A familiarity with these documents is strongly recommended for users of this module.

核心 QUIC 传输:

  • RFC 8999 — QUIC 的版本无关属性
  • RFC 9000 — QUIC:一种基于UDP的多路复用安全传输
  • RFC 9001 — 使用 TLS 保护 QUIC
  • RFC 9002 — QUIC 丢包检测与拥塞控制

核心 HTTP/3:

QUIC 扩展:

HTTP/3 扩展:

  • RFC 9218 — 可扩展的 HTTP 优先级方案
  • RFC 9220 — 使用 HTTP/3 启动 WebSockets
  • RFC 9297 — HTTP 数据报和胶囊协议
  • RFC 9412 — HTTP/3 中的 ORIGIN 扩展

操作性和信息性:

  • RFC 9308 — QUIC 传输协议的适用性
  • RFC 9312 — QUIC 传输协议的可管理性

架构#>

🌐 Architecture

quic 模块构建在三个核心抽象之上:

🌐 The quic module is built around three core abstractions:

  • QuicEndpoint:表示 QUIC 的本地 UDP 套接字绑定。它用于发送和接收 QUIC 数据包,并且可以在多个会话之间共享。单个端点可以同时用作客户端和服务器。
  • QuicSession:表示本地端点与远程对等体之间的 QUIC 连接。会话可以通过使用 quic.connect() 向远程对等体发起连接来创建,或者通过 quic.listen() 接受来自远程对等体的传入连接来创建。
  • QuicStream:表示会话中的 QUIC 流。流可以由本地或远程端创建,并且可以是双向的或单向的。

与传统的基于 TCP 的协议不同,QUIC “连接”并不固有地绑定到特定的本地端口/远程端口对。会话通过 QUIC 端点启动,但在其生命周期内可能迁移到不同的本地或远程地址,可以超出创建它的端点存在,甚至可能同时与多个端点关联。这种灵活性允许高级用例,例如连接迁移、多宿主和负载均衡。然而,在大多数情况下,端点与会话之间的一对一简单关系已经足够。

🌐 Unlike traditional TCP-based protocols, QUIC "connections" are not inherently tied to a specific local port / remote port pair. A session is initiated via a QUIC endpoint but may be migrated to a different local or remote address over its lifetime, outlive the endpoint that created it, and may even be associated with multiple endpoints simultaneously. This flexibility allows for advanced use cases such as connection migration, multi-homing, and load balancing. Most often, however, a simple one-to-one relationship between endpoint and session is sufficient.

集成 TLS 1.3#>

🌐 Integrated TLS 1.3

QUIC 协议将 TLS 1.3 直接集成到连接建立和安全性协议中。quic 模块的 API 通过公开与 TLS 相关的信息和配置选项来反映这种集成。目前无法在没有 TLS 的情况下使用 QUIC,也无法使用不同版本的 TLS。

🌐 The QUIC protocol integrates TLS 1.3 directly into the protocol for connection establishment and security. The quic module's API reflects this integration by exposing TLS-related information and configuration options. It is currently not possible to use QUIC without TLS or to use a different version of TLS.

每个 QUIC 会话都从客户端和服务器执行 TLS 握手开始,以协商应用协议(通过 ALPN)、验证服务器(并可选地验证客户端)、交换传输参数,并建立用于加密的共享密钥。

🌐 Every QUIC session starts with the client and server performing a TLS handshake to negotiate the application protocol (via ALPN), authenticate the server (and optionally the client), exchange transport parameters, and establish shared keys for encryption.

应用#>

🌐 Applications

每个 QuicSession 都与单个应用协议相关联,通过 TLS 握手期间的 ALPN 协商。quic 模块的设计总体上与应用无关,但包含对 HTTP/3 作为特定应用协议的内置支持。当使用 HTTP/3 时,quic 模块提供处理 HTTP/3 特定功能(如头部、尾部和优先级)的额外 API。对于其他应用协议,用户可以在核心 QUIC 传输功能之上实现自己的消息分帧和复用。

🌐 Every QuicSession is associated with a single application protocol, negotiated via ALPN during the TLS handshake. The quic module is designed to be application-agnostic in general but includes built-in support for HTTP/3 as a specific application protocol. When using HTTP/3, the quic module provides additional APIs for handling HTTP/3-specific features such as headers, trailers, and prioritization. For other application protocols, users can implement their own message framing and multiplexing on top of the core QUIC transport features.

在启动 TLS 握手时,客户端将在 ClientHello 中包含支持的 ALPN 协议列表。服务器会选择其中一个协议(如果有)并将其包含在 ServerHello 中。协商的协议决定了 QuicSessionQuicStream API 的行为。例如,当为 HTTP/3 协商 h3 协议时,QuicSessionQuicStream 将支持 HTTP/3 特定的功能。

🌐 When initiating a TLS handshake, the client will include a list of supported ALPN protocols in the ClientHello. The server selects one of these protocols (if any) and includes it in the ServerHello. The negotiated protocol determines how the QuicSession and QuicStream APIs behave. For example, when the h3 protocol is negotiated for HTTP/3, the QuicSession and QuicStream will support HTTP/3-specific features.

目前,quic 模块仅支持 HTTP/3 作为内置应用协议。所有其他协议必须由用户在提供的 JavaScript API 基础上实现。

🌐 Currently, the quic module only supports HTTP/3 as a built-in application protocol. All other protocols must be implemented by the user on top of the provided JavaScript API.

配置#>

🌐 Configuration

QUIC API 旨在设计得灵活且高度可配置,以支持各种使用场景。用户可以通过传递给 quic.connect()quic.listen() 函数的选项,以及在 QuicEndpointQuicSession 实例上动态配置,来配置 QUIC 传输、TLS 握手和应用行为的各个方面。该 API 还提供对详细统计信息和事件的访问,以用于监控和调试。

🌐 The QUIC API is designed to be flexible and highly configurable to support a wide range of use cases. Users can configure various aspects of the QUIC transport, TLS handshake, and application behavior via options passed to the quic.connect() and quic.listen() functions, as well as dynamically on QuicEndpoint and QuicSession instances. The API also provides access to detailed statistics and events for monitoring and debugging.

QUIC 传输参数在 TLS 握手期间交换,以协商各种传输级设置,如最大流数量、空闲超时和数据报支持。quic 模块允许用户配置其端点向对端广告的传输参数,以及访问对端广告的传输参数。这些参数与对端协调配置 QUIC 连接的能力和限制。

🌐 QUIC transport parameters are exchanged during the TLS handshake to negotiate various transport-level settings such as maximum stream counts, idle timeouts, and datagram support. The quic module allows users to configure the transport parameters their endpoint advertises to peers, as well as access the transport parameters advertised by peers. These configure the capabilities and limits of the QUIC connection in coordination with the peer.

本地端点和会话的行为也提供了一套丰富的本地设置可供配置。这些设置包括连接限制、拥塞控制、流优先级等。

🌐 A rich set of local settings is also available for configuring the behavior of the local endpoint and sessions. These include settings for connection limits, congestion control, stream prioritization, and more.

回调和承诺#>

🌐 Callbacks and Promises

quic 模块使用回调和 Promise 的组合来进行异步操作。例如,与 quic.connect() 建立连接会返回一个表示已建立会话的 Promise,而服务器端的传入会话则通过传给 quic.listen() 的回调来处理。在一个会话中,诸如传入流、数据报以及会话状态变化等事件通过 QuicSession 实例上的回调来处理。对于有明确完成点的操作,例如 TLS 握手完成或会话的优雅关闭,则使用 Promise。

🌐 The quic module uses a combination of callbacks and promises for asynchronous operations. For example, initiating a connection with quic.connect() returns a promise for the established session, while incoming sessions on the server side are handled via a callback passed to quic.listen(). Within a session, events such as incoming streams, datagrams, and session state changes are handled via callbacks on the QuicSession instance. Promises are used for operations that have a clear completion point, such as completion of the TLS handshake or graceful closure of a session.

所有回调都是同步调用的,并且可以同步返回或返回一个 Promise。如果回调返回的 Promise 被拒绝,或者抛出错误,如果没有指定 onerror 回调,对象将会被销毁,并以该错误作为原因。

🌐 All callbacks are invoked synchronously and may either return synchronously or return a promise. If a callback returns a promise that rejects, or throws an error, the object will be destroyed with the error as the reason if an onerror callback is not specified.

#>

🌐 Streams

流是 QUIC 中主要的数据承载抽象。一旦会话建立,流可以由本地端点或远程端点发起。

🌐 Streams are the primary data-carrying abstraction in QUIC. A stream can be initiated by either the local endpoint or the remote peer once a session is established.

流可以是双向的(数据在两个方向流动)或单向的(数据仅在一个方向流动)。quic 模块提供了用于创建每种类型的独立 API:session.createBidirectionalStream()session.createUnidirectionalStream()。由远程对等方启动的流通过 session.onstream 回调传递。

🌐 Streams can be either bidirectional (data flows in both directions) or unidirectional (data flows in only one direction). The quic module provides separate APIs for creating each kind: session.createBidirectionalStream() and session.createUnidirectionalStream(). Streams initiated by a remote peer are delivered via the session.onstream callback.

有两种方式可以将数据写入流:

🌐 There are two ways to write data to a stream:

  • 主体来源 — 在创建流时传入 body 选项(或调用 stream.setBody())。主体可以是字符串、ArrayBufferArrayBufferViewBlobFileHandleAsyncIterable、同步的 Iterable,或解析为这些任意类型的 Promise。一个 null 主体会立即关闭可写端。当数据已经可用或可以表示为可迭代对象时,这是最简单的方法。
  • 写入器 — 访问 stream.writer 以增量推送数据。写入器提供同步方法(writeSync()writevSync()endSync()),这些方法会立即返回,以及异步等效方法(write()writev()end()),在遇到背压时会等待缓冲区排空。writeSync() 在写入缓冲区已满时返回 false;调用者应在重试前等待缓冲区排空。

对于给定的流,这两种方法是互斥的。

🌐 These two approaches are mutually exclusive for a given stream.

读取是通过将流作为异步可迭代对象进行迭代来完成的。每次迭代都会产生一批 Uint8Array 块:

🌐 Reading is done by iterating the stream as an async iterable. Each iteration yields a batch of Uint8Array chunks:

for await (const chunks of stream) {
  for (const chunk of chunks) {
    // Process each Uint8Array chunk
  }
} 

每个流只能获取一个异步迭代器。该流也兼容 node:stream/iter 工具,例如 Stream.bytes()Stream.text()Stream.pipeTo()

🌐 Only one async iterator can be obtained per stream. The stream is also compatible with node:stream/iter utilities such as Stream.bytes(), Stream.text(), and Stream.pipeTo().

数据报#>

🌐 Datagrams

除了流,QUIC还支持不可靠的数据报(RFC 9221),用于需要低延迟、尽力而为消息传递的用例。

🌐 In addition to streams, QUIC supports unreliable datagrams (RFC 9221) for use cases that require low-latency, best-effort messaging.

数据报支持在两个层次上启用。在 QUIC 传输层,两端必须在握手期间都通告一个非零的 maxDatagramFrameSize 传输参数。对于 HTTP/3 会话,两端还必须额外将 application.enableDatagrams 设置为 true,这会在 HTTP/3 控制流上交换 SETTINGS_H3_DATAGRAM 设置。

🌐 Datagram support is enabled at two levels. At the QUIC transport level, both peers must advertise a non-zero maxDatagramFrameSize transport parameter during the handshake. For HTTP/3 sessions, both peers must additionally set application.enableDatagrams to true, which exchanges the SETTINGS_H3_DATAGRAM setting on the HTTP/3 control stream.

使用单次调用 session.sendDatagram() 发送数据报。每个数据报必须适合单个 QUIC 数据包——数据报不能被分片。最大负载大小由对等方的 maxDatagramFrameSize 和路径 MTU 决定。如果数据报过大或对等方不支持数据报,sendDatagram() 会返回 0n,而不是抛出错误。

🌐 A datagram is sent with a single call to session.sendDatagram(). Each datagram must fit within a single QUIC packet — datagrams cannot be fragmented. The maximum payload size is determined by the peer's maxDatagramFrameSize and the path MTU. If a datagram is too large or the peer does not support datagrams, sendDatagram() returns 0n rather than throwing an error.

无法保证送达。数据报可能会丢失、重复,或乱序发送。session.ondatagramstatus 回调报告每个发送的数据报是 'acknowledged''lost' 还是 'abandoned'(从不在网络上发送)。

🌐 There is no guarantee of delivery. Datagrams may be lost, duplicated, or delivered out of order. The session.ondatagramstatus callback reports whether each sent datagram was 'acknowledged', 'lost', or 'abandoned' (never sent on the wire).

0-RTT 早期数据和会话恢复#>

🌐 0-RTT early data and session resumption

QUIC 支持 0-RTT 提前数据,允许之前已与服务器建立连接的客户端在发送握手完成前的第一个数据包时发送应用数据。这可以在重新连接时消除一次完整的往返延迟。

🌐 QUIC supports 0-RTT early data, allowing a client that has previously connected to a server to send application data with its very first packet, without waiting for the handshake to complete. This can eliminate a full round-trip of latency on reconnection.

先前连接的两个状态使这成为可能:

🌐 Two pieces of state from a prior connection make this possible:

如果服务器接受会话票证,在握手完成之前发送的任何数据都是 0-RTT 早期数据。在服务器端,stream.early 对于携带早期数据的流是 true。服务器可以拒绝 0-RTT 尝试(例如,如果自票证发出以来其配置已更改)。当这种情况发生时,在 0-RTT 阶段打开的所有流都会被销毁,并且客户端的 session.onearlyrejected 回调会触发。连接会回退到正常的 1-RTT 握手,应用可以重新打开流。

🌐 If the server accepts the session ticket, any data sent before the handshake completes is 0-RTT early data. On the server side, stream.early is true for streams carrying early data. The server can reject the 0-RTT attempt (for example, if its configuration has changed since the ticket was issued). When this happens, all streams opened during the 0-RTT phase are destroyed and the client's session.onearlyrejected callback fires. The connection falls back to a normal 1-RTT handshake and the application can reopen streams.

早期数据的安全性低于握手完成后发送的数据——它可能会被攻击者重放。应用应谨慎处理 0-RTT 数据,并在早期数据阶段避免执行非幂等操作。

🌐 Early data is less secure than data sent after the handshake completes — it can potentially be replayed by an attacker. Applications should treat 0-RTT data with appropriate caution and avoid performing non-idempotent operations during the early data phase.

连接生命周期#>

🌐 Connection lifecycle

一个典型的客户会话会经过以下几个阶段:

🌐 A typical client session progresses through these stages:

  1. 使用服务器地址和选项调用 quic.connect()。这会返回一个 QuicSession
  2. TLS 握手会自动运行。session.opened 在握手完成时解析,提供协商的 ALPN、加密套件和证书验证结果。
  3. 打开流、发送数据报,并交换数据。
  4. 调用 session.close() 以启动优雅关闭。允许现有流完成,然后会话被销毁。返回的 promise(也可作为 session.closed 使用)在拆除完成时解决。

在服务器端,使用回调调用 quic.listen()。回调在每个传入会话的 TLS 握手开始后触发。传入的流通过 session.onstream 回调到达。

🌐 On the server side, call quic.listen() with a callback. The callback fires for each incoming session after the TLS handshake begins. Incoming streams arrive via the session.onstream callback.

session.destroy() 可立即进行拆解——所有打开的流都会被销毁,且会话在不等待它们完成的情况下关闭。

QuicEndpointQuicSession 支持 Symbol.asyncDispose,因此它们可以与 await using 一起用于自动清理。

错误处理#>

🌐 Error handling

quic 模块中的错误通过两种互补机制进行传递:onerror 回调和 closed Promise。

🌐 Errors in the quic module are communicated through two complementary mechanisms: the onerror callback and the closed promise.

QuicSessionQuicStream 都提供一个可选的 onerror 回调。 当会话或流因错误被销毁时 —— 包括其他用户回调抛出的错误 —— onerror 回调会在对象被销毁之前用该错误被调用。设置 onerror 也会将 closed Promise 标记为已处理,从而防止未处理拒绝警告。如果未设置 onerror,错误将仅通过 closed Promise 的拒绝传递。

🌐 Both QuicSession and QuicStream expose an optional onerror callback. When a session or stream is destroyed with an error — including errors thrown by other user callbacks — the onerror callback is invoked with the error before the object is torn down. Setting onerror also marks the closed promise as handled, preventing unhandled rejection warnings. If onerror is not set, the error is delivered solely through the rejection of the closed promise.

QuicError 类携带一个明确的数字 QUIC 错误代码 (error.errorCode),以及通常的 messagecode 属性。当 QuicError 被传递给 stream.destroy()writer.fail() 时,其 errorCode 会被用于发送给对端的 RESET_STREAMSTOP_SENDING 帧中。任何其他错误类型都会回退到协商协议的通用内部错误代码。

🌐 The QuicError class carries an explicit numeric QUIC error code (error.errorCode) alongside the usual message and code properties. When a QuicError is passed to stream.destroy() or writer.fail(), its errorCode is used in the RESET_STREAM or STOP_SENDING frame sent to the peer. Any other error type falls back to the negotiated protocol's generic internal error code.

权限模型#>

🌐 Permission model

在使用 权限模型 时,必须传递 --allow-net 标志以允许 QUIC 网络操作。如果不传递,调用 quic.connect()quic.listen() 将抛出 ERR_ACCESS_DENIED 错误。

🌐 When using the Permission Model, the --allow-net flag must be passed to allow QUIC network operations. Without it, calling quic.connect() or quic.listen() will throw an ERR_ACCESS_DENIED error.

$ node --permission --allow-fs-read=* --experimental-quic index.mjs
Error: Access to this API has been restricted. Use --allow-net to manage permissions.
  code: 'ERR_ACCESS_DENIED',
  permission: 'Net',
} 

即使没有 --allow-net,也允许创建一个 QuicEndpoint 实例而不进行连接或监听,因为在调用 quic.connect()quic.listen() 之前不会发生任何网络 I/O。

🌐 Creating a QuicEndpoint instance without connecting or listening is permitted even without --allow-net, since no network I/O occurs until quic.connect() or quic.listen() is called.

quic.connect(address[, options])#>

启动新的客户端会话。

🌐 Initiate a new client-side session.

import { connect } from 'node:quic';
import { Buffer } from 'node:buffer';

const enc = new TextEncoder();
const alpn = 'foo';
const client = await connect('123.123.123.123:8888', { alpn });
await client.createUnidirectionalStream({
  body: enc.encode('hello world'),
}); 

默认情况下,每次调用 connect(...) 都会创建一个新的本地 QuicEndpoint 实例,并绑定到一个随机的本地 IP 端口。要指定使用的确切本地地址,或者在单个本地端口上复用多个 QUIC 会话,请传递 endpoint 选项,其参数可以是 QuicEndpointEndpointOptions

🌐 By default, every call to connect(...) will create a new local QuicEndpoint instance bound to a new random local IP port. To specify the exact local address to use, or to multiplex multiple QUIC sessions over a single local port, pass the endpoint option with either a QuicEndpoint or EndpointOptions as the argument.

import { QuicEndpoint, connect } from 'node:quic';

const endpoint = new QuicEndpoint({
  address: '127.0.0.1:1234',
});

const client = await connect('123.123.123.123:8888', { endpoint }); 

quic.listen(onsession[, options])#>

  • onsession quic.OnSessionCallback
  • options quic.SessionOptions
  • 返回:<Promise> 对 quic.QuicEndpoint 的承诺

将端点配置为作为服务器监听。当远程端启动新会话时,将调用所提供的 onsession 回调,并传入创建的会话。

🌐 Configures the endpoint to listen as a server. When a new session is initiated by a remote peer, the given onsession callback will be invoked with the created session.

import { listen } from 'node:quic';

const endpoint = await listen((session) => {
  // ... handle the session
});

// Closing the endpoint allows any sessions open when close is called
// to complete naturally while preventing new sessions from being
// initiated. Once all existing sessions have finished, the endpoint
// will be destroyed. The call returns a promise that is resolved once
// the endpoint is destroyed.
await endpoint.close(); 

默认情况下,每次调用 listen(...) 都会创建一个新的本地 QuicEndpoint 实例,并绑定到一个随机的本地 IP 端口。要指定使用的确切本地地址,或在单个本地端口上复用多个 QUIC 会话,请传递 endpoint 选项,其参数可以是 QuicEndpointEndpointOptions

🌐 By default, every call to listen(...) will create a new local QuicEndpoint instance bound to a new random local IP port. To specify the exact local address to use, or to multiplex multiple QUIC sessions over a single local port, pass the endpoint option with either a QuicEndpoint or EndpointOptions as the argument.

最多,任何单个 QuicEndpoint 只能被配置为以服务器身份监听一次。

🌐 At most, any single QuicEndpoint can only be configured to listen as a server once.

quic.constants#>

一个包含用于 QUIC 配置的常用常量的对象。

🌐 An object containing commonly used constants for QUIC configuration.

quic.constants.cc#>

拥塞控制算法标识符,用于 sessionOptions.cc 选项:

🌐 Congestion control algorithm identifiers, for use with the sessionOptions.cc option:

  • quic.constants.cc.RENO — Reno 拥塞控制。
  • quic.constants.cc.CUBIC — CUBIC 拥塞控制。
  • quic.constants.cc.BBR — BBR 拥塞控制。

quic.constants.DEFAULT_CIPHERS#>

当未指定 sessionOptions.ciphers 时使用的默认 TLS 1.3 加密套件列表。

🌐 The default TLS 1.3 cipher suite list used when sessionOptions.ciphers is not specified.

quic.constants.DEFAULT_GROUPS#>

当未指定 sessionOptions.groups 时使用的默认 TLS 1.3 密钥交换组列表。

🌐 The default TLS 1.3 key-exchange group list used when sessionOptions.groups is not specified.

类:QuicEndpoint#>

🌐 Class: QuicEndpoint

QuicEndpoint 封装了 QUIC 的本地 UDP 端口绑定。它可以同时用作客户端和服务器。

🌐 A QuicEndpoint encapsulates the local UDP-port binding for QUIC. It can be used as both a client and a server.

new QuicEndpoint([options])#>

  • options quic.EndpointOptions

endpoint.address#>

端点绑定到的本地 UDP 套接字地址(如果有)。

🌐 The local UDP socket address to which the endpoint is bound, if any.

如果端点当前未绑定,则其值将为 undefined。只读。

🌐 If the endpoint is not currently bound then the value will be undefined. Read only.

endpoint.busy#>

endpoint.busy 设置为 true 时,终端将暂时拒绝创建新的会话。可读/可写。

🌐 When endpoint.busy is set to true, the endpoint will temporarily reject new sessions from being created. Read/write.

// Mark the endpoint busy. New sessions will be prevented.
endpoint.busy = true;

// Mark the endpoint free. New session will be allowed.
endpoint.busy = false; 

busy 属性在终端负载很高且需要在赶上进度时暂时拒绝新会话时非常有用。

🌐 The busy property is useful when the endpoint is under heavy load and needs to temporarily reject new sessions while it catches up.

endpoint.close()#>

优雅地关闭端点。当所有当前打开的会话关闭后,端点将自动关闭并销毁。一旦调用,新的会话将被拒绝。

🌐 Gracefully close the endpoint. The endpoint will close and destroy itself when all currently open sessions close. Once called, new sessions will be rejected.

返回一个在端点被销毁时实现的 promise。

🌐 Returns a promise that is fulfilled when the endpoint is destroyed.

endpoint.closed#>

当端点被销毁时会被 fulfillment 的承诺。这将与 endpoint.close() 函数返回的承诺相同。只读。

🌐 A promise that is fulfilled when the endpoint is destroyed. This will be the same promise that is returned by the endpoint.close() function. Read only.

endpoint.closing#>

如果已调用 endpoint.close() 且端点关闭尚未完成,则为 True。仅可读。

🌐 True if endpoint.close() has been called and closing the endpoint has not yet completed. Read only.

endpoint.destroy([error])#>

通过强制立即关闭所有打开的会话来强制关闭终端。

🌐 Forcefully closes the endpoint by forcing all open sessions to be immediately closed.

endpoint.destroyed#>

如果 endpoint.destroy() 已被调用,则为真。只读。

🌐 True if endpoint.destroy() has been called. Read only.

endpoint.listening#>

如果端点正在主动监听传入连接,则为真。只读。

🌐 True if the endpoint is actively listening for incoming connections. Read only.

endpoint.maxConnectionsPerHost#>

每个远程 IP 地址允许的最大并发连接数。 0 表示无限(默认)。可以在构造时通过 maxConnectionsPerHost 选项设置,并且可以随时动态更改。 有效范围是 065535

🌐 The maximum number of concurrent connections allowed per remote IP address. 0 means unlimited (default). Can be set at construction time via the maxConnectionsPerHost option and changed dynamically at any time. The valid range is 0 to 65535.

endpoint.maxConnectionsTotal#>

跨所有远程地址的最大并发连接总数。0 表示无限(默认)。可以在构造时通过 maxConnectionsTotal 选项设置,并可随时动态更改。有效范围是 065535

🌐 The maximum total number of concurrent connections across all remote addresses. 0 means unlimited (default). Can be set at construction time via the maxConnectionsTotal option and changed dynamically at any time. The valid range is 0 to 65535.

endpoint.setSNIContexts(entries[, options])#>

  • entries object 一个将主机名映射到 TLS 身份选项的对象。每个条目必须包括 keyscerts
  • options object
    • replace <boolean> 如果使用 true,将替换整个 SNI 映射。如果使用 false(默认),将条目合并到现有映射中。

替换或更新此端点的 SNI TLS 上下文。这允许在不重启端点的情况下更改特定主机名使用的 TLS 身份(密钥/证书)。现有会话不受影响——只有新会话会使用更新的上下文。

🌐 Replaces or updates the SNI TLS contexts for this endpoint. This allows changing the TLS identity (key/certificate) used for specific host names without restarting the endpoint. Existing sessions are unaffected — only new sessions will use the updated contexts.

endpoint.setSNIContexts({
  'api.example.com': { keys: [newApiKey], certs: [newApiCert] },
});

// Replace the entire SNI map
endpoint.setSNIContexts({
  'api.example.com': { keys: [newApiKey], certs: [newApiCert] },
}, { replace: true }); 

endpoint.stats#>

  • 类型:quic.QuicEndpoint.Stats

针对活动端点收集的统计信息。只读。

🌐 The statistics collected for an active endpoint. Read only.

endpoint[Symbol.asyncDispose]()#>

调用 endpoint.close() 并返回一个在端点关闭后完成的 Promise。

🌐 Calls endpoint.close() and returns a promise that fulfills when the endpoint has closed.

类:QuicEndpoint.Stats#>

🌐 Class: QuicEndpoint.Stats

端点收集的统计信息的视图。

🌐 A view of the collected statistics for an endpoint.

endpointStats.createdAt#>

  • 类型:<bigint> 一个指示端点创建时刻的时间戳。只读。

endpointStats.destroyedAt#>

  • 类型:<bigint> 一个指示端点被销毁时刻的时间戳。仅可读。

endpointStats.bytesReceived#>

  • 类型:<bigint> 此端点接收到的字节总数。只读。

endpointStats.bytesSent#>

  • 类型:<bigint> 此端点发送的字节总数。只读。

endpointStats.packetsReceived#>

  • 类型:<bigint> 此端点成功接收的 QUIC 数据包总数。只读。

endpointStats.packetsSent#>

  • 类型:<bigint> 此端点成功发送的 QUIC 数据包总数。只读。

endpointStats.serverSessions#>

  • 类型:<bigint> 该端点接收的对等端发起会话的总数。仅限读取。

endpointStats.clientSessions#>

  • 类型:<bigint> 此端点启动的会话总数。仅可读取。

endpointStats.serverBusyCount#>

  • 类型:<bigint> 由于端点被标记为忙而导致初始数据包被拒绝的总次数。只读。

endpointStats.retryCount#>

  • 类型:<bigint> 此端点上的 QUIC 重试尝试总数。仅可读。

endpointStats.versionNegotiationCount#>

  • 类型:<bigint> 由于 QUIC 版本不匹配而被拒绝的会话总数。仅限读取。

endpointStats.statelessResetCount#>

  • 类型:<bigint> 此端点处理的无状态重置总数。仅限读取。

endpointStats.immediateCloseCount#>

  • 类型:<bigint> 握手结束前关闭的会话总数。仅限读取。

类:QuicSession#>

🌐 Class: QuicSession

QuicSession 表示 QUIC 连接的本地端。

🌐 A QuicSession represents the local side of a QUIC connection.

session.close([options])#>

  • options <Object>
    • code <bigint> | <number> 要包含在发送给对等方的 CONNECTION_CLOSE 帧中的错误代码。默认值: 0(无错误)。
    • type <string> 要么是 'transport' 要么是 'application'。确定在 CONNECTION_CLOSE 帧中使用的错误代码命名空间。当为 'transport'(默认值)时,帧类型为 0x1c,并且代码被解释为 QUIC 传输错误。当为 'application' 时,帧类型为 0x1d,代码是应用特定的。默认值: 'transport'
    • reason <string>CONNECTION_CLOSE 帧中可选择包含的人类可读原因字符串。根据 RFC 9000,这仅用于诊断目的,不应用于机器可读的错误描述。
  • 返回:<Promise>

启动会话的优雅关闭。现有的数据流将被允许完成,但不会打开新的数据流。一旦所有数据流关闭,会话将被销毁。返回的 promise 将在会话被销毁后完成。如果指定了非零的 code,promise 将根据 type 拒绝,并返回 ERR_QUIC_TRANSPORT_ERRORERR_QUIC_APPLICATION_ERROR

🌐 Initiate a graceful close of the session. Existing streams will be allowed to complete but no new streams will be opened. Once all streams have closed, the session will be destroyed. The returned promise will be fulfilled once the session has been destroyed. If a non-zero code is specified, the promise will reject with an ERR_QUIC_TRANSPORT_ERROR or ERR_QUIC_APPLICATION_ERROR depending on the type.

session.opened#>

  • 类型:<Promise> 用于 <Object>
    • local <net.SocketAddress> 本地套接字地址。
    • remote <net.SocketAddress> 远程套接字地址。
    • servername <string> 在握手过程中协商的 SNI 服务器名称。
    • protocol <string> 在握手期间协商的 ALPN 协议。
    • cipher <string> 协商的 TLS 密码套件的名称。
    • cipherVersion <string> 密码套件的 TLS 协议版本(例如,'TLSv1.3')。
    • validationErrorReason <string> 如果证书验证失败,返回原因字符串。如果验证成功,则返回空字符串。
    • validationErrorCode <number> 如果证书验证失败,则显示错误代码。如果验证成功,则为 0
    • earlyDataAttempted <boolean> 是否尝试了 0-RTT 早期数据。
    • earlyDataAccepted <boolean> 服务器是否接受了 0-RTT 提前数据。

一个在 TLS 握手成功完成后会被履行的承诺。解析后的值包含有关已建立会话的信息,包括协商的协议、密码套件、证书验证状态以及 0-RTT 早期数据状态。

🌐 A promise that is fulfilled once the TLS handshake completes successfully. The resolved value contains information about the established session including the negotiated protocol, cipher suite, certificate validation status, and 0-RTT early data status.

如果握手失败或会话在握手完成之前被销毁,该承诺将被拒绝。

🌐 If the handshake fails or the session is destroyed before the handshake completes, the promise will be rejected.

session.closed#>

会话销毁后实现的 promise。

🌐 A promise that is fulfilled once the session is destroyed.

session.closing#>

如果 session.close() 已被调用且会话尚未被销毁,则为真。只读。

🌐 True if session.close() has been called and the session has not yet been destroyed. Read only.

session.destroy([error[, options]])#>

  • error <any>
  • options <Object>
    • code <bigint> | <number> 发送给对端的 CONNECTION_CLOSE 帧中要包含的错误代码。默认值: 0
    • type <string> 要么 'transport',要么 'application'默认值: 'transport'
    • reason <string> 包含在 CONNECTION_CLOSE 帧中的可选可读原因字符串。

立即销毁会话。所有流将被销毁,会话将被关闭。如果提供了 error 且设置了 session.onerror,在销毁之前会调用 onerror 回调。session.closed promise 将以错误拒绝。如果提供了 options,发送给对等方的 CONNECTION_CLOSE 帧将包含指定的错误代码、类型和原因。

🌐 Immediately destroy the session. All streams will be destroyed and the session will be closed. If error is provided and session.onerror is set, the onerror callback is invoked before destruction. The session.closed promise will reject with the error. If options is provided, the CONNECTION_CLOSE frame sent to the peer will include the specified error code, type, and reason.

session.destroyed#>

如果 session.destroy() 已被调用,则为真。只读。

🌐 True if session.destroy() has been called. Read only.

session.endpoint#>

创建此会话的端点。如果会话已被销毁,则返回 null。只读。

🌐 The endpoint that created this session. Returns null if the session has been destroyed. Read only.

session.onerror#>

在会话因错误而被销毁时可选调用的回调函数。这包括由用户回调抛出或拒绝导致的错误(参见 回调错误处理)。回调函数接收一个参数:触发销毁的错误。如果 onerror 回调本身抛出错误或返回的 Promise 被拒绝,该错误将作为未捕获的异常出现。可读/可写。

🌐 An optional callback invoked when the session is destroyed with an error. This includes errors caused by user callbacks that throw or reject (see Callback error handling). The callback receives a single argument: the error that triggered the destruction. If the onerror callback itself throws or returns a promise that rejects, the error is surfaced as an uncaught exception. Read/write.

也可以通过 quic.connect()quic.listen() 中的 onerror 选项进行设置。

🌐 Can also be set via the onerror option in quic.connect() or quic.listen().

session.onstream#>

  • 类型:quic.OnStreamCallback

当远程端启动新流时要调用的回调。可读/写。

🌐 The callback to invoke when a new stream is initiated by a remote peer. Read/write.

session.ondatagram#>

  • 类型:quic.OnDatagramCallback

当从远程节点接收到新的数据报时要调用的回调。可读/可写。

🌐 The callback to invoke when a new datagram is received from a remote peer. Read/write.

session.ondatagramstatus#>

  • 类型:quic.OnDatagramStatusCallback

当数据报的状态更新时要调用的回调。可读写。

🌐 The callback to invoke when the status of a datagram is updated. Read/write.

session.onearlyrejected#>

当服务器拒绝 0-RTT 早期数据时要调用的回调。当此回调触发时,在 0-RTT 阶段打开的所有流都已被销毁。如果需要,应用应重新打开流。读/写。

🌐 The callback to invoke when the server rejects 0-RTT early data. When this fires, all streams that were opened during the 0-RTT phase have been destroyed. The application should re-open streams if needed. Read/write.

当服务器拒绝客户端的 0-RTT 尝试时,此回调仅在客户端触发。连接将回退到 1-RTT 并正常继续。

🌐 This callback only fires on the client side when the server rejects the client's 0-RTT attempt. The connection falls back to 1-RTT and continues normally.

session.onpathvalidation#>

  • 类型:quic.OnPathValidationCallback

路径验证更新时要调用的回调。可读写。

🌐 The callback to invoke when the path validation is updated. Read/write.

session.onsessionticket#>

  • 类型:quic.OnSessionTicketCallback

在收到新会话票证时调用的回调。可读/可写。

🌐 The callback to invoke when a new session ticket is received. Read/write.

session.onversionnegotiation#>

  • 类型:quic.OnVersionNegotiationCallback

当发起版本协商时要调用的回调函数。可读/可写。

🌐 The callback to invoke when a version negotiation is initiated. Read/write.

session.onhandshake#>

  • 类型:quic.OnHandshakeCallback

TLS 握手完成时调用的回调。可读/可写。

🌐 The callback to invoke when the TLS handshake is completed. Read/write.

session.onnewtoken#>

  • 类型:quic.OnNewTokenCallback

当从服务器接收到 NEW_TOKEN 令牌时要调用的回调函数。该令牌可以作为未来连接到同一服务器时的 token 选项传递,以跳过地址验证。可读/可写。

🌐 The callback to invoke when a NEW_TOKEN token is received from the server. The token can be passed as the token option on a future connection to the same server to skip address validation. Read/write.

session.onorigin#>

  • 类型:quic.OnOriginCallback

当从服务器收到 ORIGIN 帧(RFC 9412)时调用的回调,指示服务器拥有权威的源。可读/可写。

🌐 The callback to invoke when an ORIGIN frame (RFC 9412) is received from the server, indicating which origins the server is authoritative for. Read/write.

session.ongoaway#>

当对等方发送 HTTP/3 GOAWAY 帧时调用的回调,表示它正在启动优雅关闭。回调接收 (lastStreamId),其中 lastStreamId 是一个 {bigint}

🌐 The callback to invoke when the peer sends an HTTP/3 GOAWAY frame, indicating it is initiating a graceful shutdown. The callback receives (lastStreamId) where lastStreamId is a {bigint}:

  • lastStreamId-1n 时,对端发送了关闭通知(意图关闭),但未指定流边界。所有现有的流仍可被处理。
  • lastStreamId>= 0n 时,它是对等方可能已处理的最高流 ID。ID 高于此值的流未被处理,可以在新连接上安全重试。

在接收到 GOAWAY 后,session.createBidirectionalStream() 将抛出 ERR_INVALID_STATE。现有的流将继续,直到它们完成或会话关闭。

🌐 After GOAWAY is received, session.createBidirectionalStream() will throw ERR_INVALID_STATE. Existing streams continue until they complete or the session closes.

此回调仅与 HTTP/3 会话相关。读/写。

🌐 This callback is only relevant for HTTP/3 sessions. Read/write.

session.onkeylog#>

  • 类型:quic.OnKeylogCallback

当 TLS 密钥材料可用时要调用的回调。要求 sessionOptions.keylogtrue。每次调用接收一行 NSS 密钥日志格式 文本(包括结尾的换行符)。这对于使用 Wireshark 等工具解密数据包捕获非常有用。可读/可写。

🌐 The callback to invoke when TLS key material is available. Requires sessionOptions.keylog to be true. Each invocation receives a single line of NSS Key Log Format text (including a trailing newline). This is useful for decrypting packet captures with tools like Wireshark. Read/write.

也可以通过 quic.connect()quic.listen() 中的 onkeylog 选项进行设置。

🌐 Can also be set via the onkeylog option in quic.connect() or quic.listen().

session.onqlog#>

  • 类型:quic.OnQlogCallback

当 qlog 数据可用时调用的回调。要求 sessionOptions.qlogtrue。回调接收一个字符串块格式的 JSON-序列 qlog 数据和一个布尔 fin 标志。当 fintrue 时,该块是此会话的最终 qlog 输出,连接的块形成完整的 qlog 跟踪。可读/可写。

🌐 The callback to invoke when qlog data is available. Requires sessionOptions.qlog to be true. The callback receives a string chunk of JSON-SEQ formatted qlog data and a boolean fin flag. When fin is true, the chunk is the final qlog output for this session and the concatenated chunks form a complete qlog trace. Read/write.

Qlog 数据在连接生命周期中到达。第一个数据块包含带有格式元数据的 qlog 头。后续数据块包含跟踪事件。最后一个数据块(其中 fin 设置为 true)在会话销毁期间发出,并完成 JSON-SEQ 输出。

🌐 Qlog data arrives during the connection lifecycle. The first chunk contains the qlog header with format metadata. Subsequent chunks contain trace events. The final chunk (with fin set to true) is emitted during session destruction and completes the JSON-SEQ output.

也可以通过 quic.connect()quic.listen() 中的 onqlog 选项进行设置。

🌐 Can also be set via the onqlog option in quic.connect() or quic.listen().

session.createBidirectionalStream([options])#>

  • options <Object>
    • body <string> | <ArrayBuffer> | <SharedArrayBuffer> | <ArrayBufferView> | <Blob> | <FileHandle> | <AsyncIterable> | <Iterable> | <Promise> | <null> 出站主体来源。有关支持的类型,请参见stream.setBody()。若省略,流将以半关闭状态开始(可写端打开,无主体排队)。
    • headers <Object> 要发送的初始请求或响应头。仅在会话支持头时使用(例如 HTTP/3)。如果未指定 body 且提供了 headers,则流将被视为仅包含头(终端)。
    • priority <string> 流的优先级别。可选值为 'high''default''low'默认值: 'default'
    • incremental <boolean>true 时,该流的数据可能会与同一优先级的其他流的数据交错。 当 false 时,该流应在同优先级的同伴之前完成。 默认: false
    • highWaterMark <number>writeSync() 返回 false 之前,写入器将缓冲的最大字节数。当缓冲的数据超过此限制时,调用者应在写入更多数据之前等待清空。默认值: 65536(64 KB)。
    • onheaders <Function> 接收到初始响应头时的回调。 使用 (headers) 调用。
    • ontrailers <Function> 接收尾部头的回调。调用时使用 (trailers)
    • oninfo <Function> 收到信息性(1xx)头时的回调。使用 (headers) 调用。
    • onwanttrailers <Function> 当应发送标尾时的回调。调用时不带参数;在回调中使用 stream.sendTrailers()
  • 返回:<Promise> 用于 quic.QuicStream

打开一个新的双向流。如果未指定 body 选项,传出流将被半关闭。priorityincremental 选项仅在会话支持优先级时使用(例如 HTTP/3)。headersonheadersontrailersoninfoonwanttrailers 选项仅在会话支持头部时使用(例如 HTTP/3)。

🌐 Open a new bidirectional stream. If the body option is not specified, the outgoing stream will be half-closed. The priority and incremental options are only used when the session supports priority (e.g. HTTP/3). The headers, onheaders, ontrailers, oninfo, and onwanttrailers options are only used when the session supports headers (e.g. HTTP/3).

session.createUnidirectionalStream([options])#>

  • options <Object>
    • body <string> | <ArrayBuffer> | <SharedArrayBuffer> | <ArrayBufferView> | <Blob> | <FileHandle> | <AsyncIterable> | <Iterable> | <Promise> | <null> 出站主体源。有关支持的类型,请参见 stream.setBody()。省略时,流会立即关闭。
    • headers <Object> 要发送的初始请求头。
    • priority <string> 流的优先级别。可选值为 'high''default''low'默认值: 'default'
    • incremental <boolean>true 时,该流的数据可能会与同一优先级的其他流的数据交错。 当 false 时,该流应在同优先级的同伴之前完成。 默认: false
    • highWaterMark <number>writeSync() 返回 false 之前,写入器将缓冲的最大字节数。当缓冲的数据超过此限制时,调用者应在写入更多数据之前等待清空。默认值: 65536(64 KB)。
    • onheaders <Function> 接收到初始响应头时的回调。 使用 (headers) 调用。
    • ontrailers <Function> 接收尾部头的回调。调用时使用 (trailers)
    • oninfo <Function> 收到信息性(1xx)头时的回调。使用 (headers) 调用。
    • onwanttrailers <Function> 在应该发送标尾时的回调。
  • 返回:<Promise> 用于 quic.QuicStream

打开一个新的单向流。如果未指定 body 选项,出站流将被关闭。priorityincremental 选项仅在会话支持优先级时使用(例如 HTTP/3)。

🌐 Open a new unidirectional stream. If the body option is not specified, the outgoing stream will be closed. The priority and incremental options are only used when the session supports priority (e.g. HTTP/3).

session.path#>

与会话关联的本地和远程套接字地址。只读。

🌐 The local and remote socket addresses associated with the session. Read only.

session.sendDatagram(datagram[, encoding])#>

向远程对等方发送不可靠的数据报,并返回数据报 ID 的承诺。

🌐 Sends an unreliable datagram to the remote peer, returning a promise for the datagram ID.

如果 datagram 是字符串,它将使用指定的 encoding 进行编码。

🌐 If datagram is a string, it will be encoded using the specified encoding.

如果 datagram 是一个 ArrayBufferView,字节将被复制到一个内部缓冲区;调用者的源缓冲区保持不变,并且可以在调用返回后立即重复使用或修改。希望确保其源在调用后不会被修改的调用者(例如,当将缓冲区交给另一个异步消费者时)可以在传递缓冲区之前自己调用 ArrayBuffer.prototype.transfer()

🌐 If datagram is an ArrayBufferView, the bytes are copied into an internal buffer; the caller's source buffer is unchanged and may be reused or mutated immediately after the call returns. Callers that want to ensure their source cannot be mutated after the call (for example, when handing the buffer off to another async consumer) can call ArrayBuffer.prototype.transfer() themselves before passing the buffer.

如果 datagramPromise,则在发送之前会等待。如果在等待时会话关闭,则会静默返回 0n(数据报本质上是不可靠的)。

🌐 If datagram is a Promise, it will be awaited before sending. If the session closes while awaiting, 0n is returned silently (datagrams are inherently unreliable).

如果数据报负载长度为零(编码后的空字符串、分离的缓冲区或零长度视图),将返回 0n,并且不会发送任何数据报。

🌐 If the datagram payload is zero-length (empty string after encoding, detached buffer, or zero-length view), 0n is returned and no datagram is sent.

对于 HTTP/3 会话,对等方必须通过 application: { enableDatagrams: true } 广告 SETTINGS_H3_DATAGRAM=1 才能发送数据报。如果对等方的设置是 0sendDatagram() 返回 0n(根据 RFC 9297 第 3 条,一端点不得发送 HTTP 数据报,除非对等方表示支持)。

🌐 For HTTP/3 sessions, the peer must advertise SETTINGS_H3_DATAGRAM=1 (via application: { enableDatagrams: true }) for datagrams to be sent. If the peer's setting is 0, sendDatagram() returns 0n (per RFC 9297 §3, an endpoint MUST NOT send HTTP Datagrams unless the peer indicated support).

数据报不能被分片——每个数据报必须适合一个 QUIC 数据包。最大数据报大小由对等方的 maxDatagramFrameSize 传输参数决定(对等方在握手期间会通告该参数)。如果对等方将其设置为 0,则不支持数据报,并且会返回 0n。如果数据报超过对等方的限制,它将被静默丢弃,并返回 0n。本端的 maxDatagramFrameSize 传输参数(默认值:1200 字节)控制本端向对等方通告自身最大值的能力。

🌐 Datagrams cannot be fragmented — each must fit within a single QUIC packet. The maximum datagram size is determined by the peer's maxDatagramFrameSize transport parameter (which the peer advertises during the handshake). If the peer sets this to 0, datagrams are not supported and 0n will be returned. If the datagram exceeds the peer's limit, it will be silently dropped and 0n returned. The local maxDatagramFrameSize transport parameter (default: 1200 bytes) controls what this endpoint advertises to the peer as its own maximum.

session.certificate#>

本地证书作为一个具有属性的对象,例如 subjectissuervalid_fromvalid_tofingerprint 等。如果会话被销毁或没有可用的证书,则返回 undefined

🌐 The local certificate as an object with properties such as subject, issuer, valid_from, valid_to, fingerprint, etc. Returns undefined if the session is destroyed or no certificate is available.

session.peerCertificate#>

将对等方的证书作为一个对象,其中包含 subjectissuervalid_fromvalid_tofingerprint 等属性。如果会话已被销毁或对等方未提供证书,则返回 undefined

🌐 The peer's certificate as an object with properties such as subject, issuer, valid_from, valid_to, fingerprint, etc. Returns undefined if the session is destroyed or the peer did not present a certificate.

session.ephemeralKeyInfo#>

会话的短暂密钥信息,具有诸如 typenamesize 等属性。仅在客户端会话中可用。如果是服务器会话或会话已被销毁,则返回 undefined

🌐 The ephemeral key information for the session, with properties such as type, name, and size. Only available on client sessions. Returns undefined for server sessions or if the session is destroyed.

session.maxDatagramSize#>

对等方将接受的最大数据报有效载荷大小(字节)。 这是从对等方的 maxDatagramFrameSize 传输参数中减去 DATAGRAM 帧开销(类型字节和可变长度整数编码)得出的。如果对等方不支持数据报或握手尚未完成,则返回 0。大于该值的数据报将不会被发送。

🌐 The maximum datagram payload size in bytes that the peer will accept. This is derived from the peer's maxDatagramFrameSize transport parameter minus the DATAGRAM frame overhead (type byte and variable-length integer encoding). Returns 0 if the peer does not support datagrams or if the handshake has not yet completed. Datagrams larger than this value will not be sent.

session.maxPendingDatagrams#>

可以排队发送的数据报的最大数量。当调用 sendDatagram() 时,数据报会被排队,并由数据包序列化循环与流数据一起机会性发送。当队列已满时,sessionOptions.datagramDropPolicy 决定丢弃最旧的数据报还是最新的数据报。被丢弃的数据报会通过 ondatagramstatus 回调报告为丢失。

🌐 The maximum number of datagrams that can be queued for sending. Datagrams are queued when sendDatagram() is called and sent opportunistically alongside stream data by the packet serialization loop. When the queue is full, the sessionOptions.datagramDropPolicy determines whether the oldest or newest datagram is dropped. Dropped datagrams are reported as lost via the ondatagramstatus callback.

此属性可以动态更改,以根据应用活动或内存压力调整队列容量。有效范围是 065535

🌐 This property can be changed dynamically to adjust queue capacity based on application activity or memory pressure. The valid range is 0 to 65535.

session.stats#>

  • 类型:quic.QuicSession.Stats

返回当前会话的统计数据。仅可读取。

🌐 Return the current statistics for the session. Read only.

session.updateKey()#>

启动会话的密钥更新。

🌐 Initiate a key update for the session.

session[Symbol.asyncDispose]()#>

调用 session.close() 并返回一个在会话关闭后完成的 Promise。

🌐 Calls session.close() and returns a promise that fulfills when the session has closed.

类:QuicSession.Stats#>

🌐 Class: QuicSession.Stats

sessionStats.createdAt#>

sessionStats.closingAt#>

sessionStats.handshakeCompletedAt#>

sessionStats.handshakeConfirmedAt#>

sessionStats.bytesReceived#>

sessionStats.bytesSent#>

sessionStats.bidiInStreamCount#>

sessionStats.bidiOutStreamCount#>

sessionStats.uniInStreamCount#>

sessionStats.uniOutStreamCount#>

sessionStats.maxBytesInFlight#>

sessionStats.bytesInFlight#>

sessionStats.blockCount#>

sessionStats.cwnd#>

sessionStats.latestRtt#>

sessionStats.minRtt#>

sessionStats.rttVar#>

sessionStats.smoothedRtt#>

sessionStats.ssthresh#>

sessionStats.datagramsReceived#>

sessionStats.datagramsSent#>

sessionStats.datagramsAcknowledged#>

sessionStats.datagramsLost#>

类:QuicError#>

🌐 Class: QuicError

稳定性: 1 - 实验性

QuicError 是一个 Error 子类,携带一个明确的数字 QUIC 错误码。使用它可以中止 QUIC 流或会话,并带有特定的应用协议定义的错误码,而不是让实现选择通用的回退错误码。

🌐 A QuicError is an Error subclass that carries an explicit numeric QUIC error code. Use it to abort a QUIC stream or session with a specific application-protocol-defined error code rather than letting the implementation pick a generic fallback.

该类从 node:quic 导出:

🌐 The class is exported from node:quic:

import { QuicError } from 'node:quic';const { QuicError } = require('node:quic');

当向发出帧的 API(writer.fail()stream.destroy())提供 QuicError 时,QUIC 堆栈会使用 error.errorCode 作为生成帧的线编码。 当提供任何其他值(例如普通的 Error)时,实现在回退到协商的应用协议的“内部错误”代码(HTTP/3 为 H3_INTERNAL_ERROR (0x102),或原生 QUIC 的 QUIC 传输层 INTERNAL_ERROR (0x1))。

🌐 When a QuicError is supplied to APIs that emit a wire frame (writer.fail(), stream.destroy()), the QUIC stack uses error.errorCode as the wire code for the resulting frame. When any other value is supplied (for example a plain Error), the implementation falls back to the negotiated application protocol's "internal error" code (H3_INTERNAL_ERROR (0x102) for HTTP/3, or the QUIC transport-layer INTERNAL_ERROR (0x1) for raw QUIC).

Node.js 错误代码(error.code)默认是 'ERR_QUIC_STREAM_ABORTED'。需要更具体代码字符串的调用者可以通过 options.code 覆盖它 —— 数字 QUIC 代码不受影响。

🌐 The Node.js error code (error.code) defaults to 'ERR_QUIC_STREAM_ABORTED'. Callers who need a more specific code string can override it via options.code — the numeric QUIC code is unaffected.

Node.js 错误代码固定为 'ERR_QUIC_STREAM_ABORTED',以便 catch 块可以区分 QuicError 与其他 Node.js 错误,而无需检查原型链。数字 QUIC 代码存在于单独的 error.errorCode 属性上,以避免与 Node.js 约定的 error.code 为字符串发生冲突。

🌐 The Node.js error code is fixed at 'ERR_QUIC_STREAM_ABORTED' so that catch blocks can distinguish a QuicError from other Node.js errors without checking the prototype chain. The numeric QUIC code lives on the separate error.errorCode property to avoid colliding with the Node.js convention that error.code is a string.

new QuicError(message, options)#>

  • message <string> 错误的可读描述。
  • options <Object>
    • errorCode <bigint> | <number> 数字 QUIC 错误代码。数字会被强制为 BigInt。必须是非负的 62 位无符号 varint(0n <= errorCode <= 2n ** 62n - 1n)。
    • code <string> 分配给 error.code 的 Node.js 风格错误代码字符串。默认为 'ERR_QUIC_STREAM_ABORTED'
    • type <string> 可以是 'application'(默认)或 'transport'。表示代码是由协商的应用协议(例如 HTTP/3 的 RFC 9114)定义,还是由 QUIC 传输层(RFC 9000)定义。流重置总是携带应用代码,因此默认值是 'application'
import { QuicError } from 'node:quic';

const err = new QuicError('rejecting stream', { errorCode: 0x10cn });
console.log(err.code);       // 'ERR_QUIC_STREAM_ABORTED'
console.log(err.errorCode);  // 268n
console.log(err.type);       // 'application'

const custom = new QuicError('custom failure', {
  errorCode: 0x10cn,
  code: 'ERR_MY_QUIC_FAILURE',
});
console.log(custom.code);    // 'ERR_MY_QUIC_FAILURE' 

error.errorCode#>

此错误携带的数字 QUIC 错误代码。

🌐 The numeric QUIC error code carried by this error.

error.type#>

'application''transport'。表示 error.errorCode 的命名空间。

🌐 Either 'application' or 'transport'. Indicates the namespace of error.errorCode.

类:QuicStream#>

🌐 Class: QuicStream

stream.closed#>

当流完全关闭时会兑现的承诺。当流干净地关闭(包括空闲超时)时,它会被解决。当流由于 QUIC 错误而关闭时(例如,同行重置流,带有非零错误代码的 CONNECTION_CLOSE),它会以 ERR_QUIC_APPLICATION_ERRORERR_QUIC_TRANSPORT_ERROR 被拒绝。

🌐 A promise that is fulfilled when the stream is fully closed. It resolves when the stream closes cleanly (including idle timeout). It rejects with an ERR_QUIC_APPLICATION_ERROR or ERR_QUIC_TRANSPORT_ERROR when the stream is closed due to a QUIC error (e.g., stream reset by the peer, CONNECTION_CLOSE with a non-zero error code).

stream.destroy([error[, options]])#>

  • error <any>
  • options <Object>
    • code <bigint> | <number> 要包含在发送给对等方的 RESET_STREAMSTOP_SENDING 帧中的应用错误代码。数字会被强制转换为 BigInt。如果省略,则线编码从 error 派生(见下文)。
    • reason <string> 一个可选的人类可读原因字符串。为了与 session.close()session.destroy() 保持对称而被接受,但 不会在网络上传输——RESET_STREAMSTOP_SENDING 都不包含原因字段。提供用于应用日志记录以及 stream.onerror 回调的使用。

立即且突然地销毁流。如果提供了 error 且设置了 stream.onerror,则在销毁之前调用 onerror 回调。stream.closed Promise 会因错误而被拒绝。

🌐 Immediately and abruptly destroys the stream. If error is provided and stream.onerror is set, the onerror callback is invoked before destruction. The stream.closed promise rejects with the error.

当流被 error(或明确使用 options.code)销毁时,QUIC 堆栈会向对等方发出中止信号:

🌐 When the stream is destroyed with an error (or with an explicit options.code), the QUIC stack signals the abort to the peer:

  • 如果可写端仍然打开,将发送一个 RESET_STREAM 帧。
  • 如果可读端仍然开放(双向流,或远程发起的单向流),将发送一个 STOP_SENDING 帧。

两个帧都携带相同的线路代码,按以下优先顺序解析:

🌐 Both frames carry the same wire code, resolved with the following precedence:

  1. options.code,当明确提供时。
  2. error.errorCode,当 errorQuicError 时。
  3. 协商应用协议的“内部错误”代码(HTTP/3 的 H3_INTERNAL_ERROR (0x102),或原始 QUIC 的传输层 INTERNAL_ERROR (0x1))。

一次干净的销毁——没有 error 也没有 options.code——不会发出 RESET_STREAMSTOP_SENDING;流的现有关闭机制会处理拆卸。

🌐 A clean destroy — no error and no options.code — does not emit RESET_STREAM or STOP_SENDING; the stream's existing close machinery handles teardown.

有关可用的流中止 API 的概述,请参见 中止流

🌐 See Aborting a stream for an overview of the available stream-abort APIs.

stream.destroyed#>

如果已调用 stream.destroy(),则为真。

🌐 True if stream.destroy() has been called.

中止流#>

🌐 Aborting a stream

QuicStream 可以通过三种方式中止,每种方式都会产生不同的传输帧副作用:

🌐 A QuicStream can be aborted in three ways, each producing different wire-frame side effects:

  • writer.fail(reason) — 仅中止可写的一侧。向对端发送 RESET_STREAM。可读的一侧不受影响;任何已经缓冲的可读数据仍然可用。
  • stream.destroy() 使用 error 参数 — 完全中断流。向任何仍然打开的可写端发送 RESET_STREAM,并向任何仍然打开的可读端发送 STOP_SENDING。该线代码源自 error(优先规则见 stream.destroy())。
  • stream.destroy() 带有一个显式的 options.code — 与之前的形式相同,但使用调用者提供的线路代码,该代码优先于 error 所携带的任何代码。

errorQuicError 时,其 error.errorCode 用作 writer.fail()stream.destroy() 的线码。否则,实现将回退到协商的应用协议的“内部错误”代码(参见 QuicError)。

🌐 When error is a QuicError, its error.errorCode is used as the wire code for both writer.fail() and stream.destroy(). Otherwise the implementation falls back to the negotiated application protocol's "internal error" code (see QuicError).

stream.early#>

如果在TLS握手完成之前,该流上的任何数据被作为0-RTT(早期数据)接收,则为真。早期数据的安全性较低,可能被攻击者重放。应用应对早期数据保持适当的谨慎。

🌐 True if any data on this stream was received as 0-RTT (early data) before the TLS handshake completed. Early data is less secure and could potentially be replayed by an attacker. Applications should treat early data with appropriate caution.

此属性仅在服务器端有意义。在客户端,它始终是 false

🌐 This property is only meaningful on the server side. On the client side, it is always false.

stream.direction#>

流的方向性,或者如果流已被销毁或仍在等待中,则为 null。只读。

🌐 The directionality of the stream, or null if the stream has been destroyed or is still pending. Read only.

stream.highWaterMark#>

写入器在 writeSync() 返回 false 之前将缓冲的最大字节数。当缓冲的数据超过此限制时,调用者在写入更多数据之前应等待排空(drain)。

🌐 The maximum number of bytes that the writer will buffer before writeSync() returns false. When the buffered data exceeds this limit, the caller should wait for drain before writing more.

该值可以随时动态更改。这对于通过 onstream 回调接收的流尤其有用,其中默认值(65536)可能需要根据应用需求进行调整。有效范围是 04294967295

🌐 The value can be changed dynamically at any time. This is particularly useful for streams received via the onstream callback, where the default (65536) may need to be adjusted based on application needs. The valid range is 0 to 4294967295.

stream.id#>

流 ID,如果流已被销毁或仍在挂起,则为 null。只读。

🌐 The stream ID, or null if the stream has been destroyed or is still pending. Read only.

stream.onerror#>

在流因错误而被销毁时可选调用的回调函数。这包括用户回调抛出或拒绝引起的错误(见 回调错误处理)。回调函数接收一个参数:触发销毁的错误。如果 onerror 回调本身抛出错误或返回一个被拒绝的 Promise,该错误将作为未捕获异常显现。读/写。

🌐 An optional callback invoked when the stream is destroyed with an error. This includes errors caused by user callbacks that throw or reject (see Callback error handling). The callback receives a single argument: the error that triggered the destruction. If the onerror callback itself throws or returns a promise that rejects, the error is surfaced as an uncaught exception. Read/write.

stream.onblocked#>

  • 类型:quic.OnBlockedCallback

当流被阻塞时要调用的回调。可读/可写。

🌐 The callback to invoke when the stream is blocked. Read/write.

stream.onreset#>

  • 类型:quic.OnStreamErrorCallback

当对等方通过发送 RESET_STREAM 帧中止流的某个方向(对等方放弃其可写端,因此我们的可读端将不再接收数据)或发送 STOP_SENDING 帧(对等方要求我们停止在可写端写入)时要调用的回调。

🌐 The callback to invoke when the peer aborts a direction of the stream by sending a RESET_STREAM frame (the peer abandons their writable side, so no further data will arrive on our readable side) or a STOP_SENDING frame (the peer asks us to stop writing on our writable side).

回调接收一个 Node.js 错误,其 errorCode (bigint) 属性携带来自数据帧的应用错误代码。

🌐 The callback receives a Node.js error whose errorCode (bigint) property carries the application error code from the wire frame.

当此回调触发时,流不会自动销毁——应用可以选择如何响应。常见模式是:忽略(并继续使用双向流中仍然活跃的方向)、使用 writer.fail() 中止另一方向,或使用 stream.destroy() 拆除整个流。读取/写入。

🌐 The stream is not automatically destroyed when this callback fires — the application chooses how to react. Common patterns are: ignore (and continue using the still-active direction on a bidirectional stream), abort the other direction with writer.fail(), or tear down the whole stream with stream.destroy(). Read/write.

stream.headers#>

在此流上接收到的缓冲初始头,或者如果应用不支持头或尚未接收到头,则为 undefined。对于服务器端流,这包含请求头(例如,:method:path:scheme)。对于客户端流,这包含响应头(例如,:status)。

🌐 The buffered initial headers received on this stream, or undefined if the application does not support headers or no headers have been received yet. For server-side streams, this contains the request headers (e.g., :method, :path, :scheme). For client-side streams, this contains the response headers (e.g., :status).

头部名称是小写字符串。多值头部表示为数组。该对象有 __proto__: null

🌐 Header names are lowercase strings. Multi-value headers are represented as arrays. The object has __proto__: null.

stream.onheaders#>

当在流上接收到初始头时要调用的回调。回调接收 (headers),其中 headers 是一个对象(格式与 stream.headers 相同)。对于 HTTP/3,这在服务器端提供请求伪头,在客户端提供响应头。如果在不支持头的会话上设置,则抛出 ERR_INVALID_STATE。可读/可写。

🌐 The callback to invoke when initial headers are received on the stream. The callback receives (headers) where headers is an object (same format as stream.headers). For HTTP/3, this delivers request pseudo-headers on the server side and response headers on the client side. Throws ERR_INVALID_STATE if set on a session that does not support headers. Read/write.

stream.ontrailers#>

当从对端接收到尾部头时调用的回调。回调接收 (trailers),其中 trailers 是与 stream.headers 相同格式的对象。如果在不支持头的会话上设置,则抛出 ERR_INVALID_STATE。可读/可写。

🌐 The callback to invoke when trailing headers are received from the peer. The callback receives (trailers) where trailers is an object in the same format as stream.headers. Throws ERR_INVALID_STATE if set on a session that does not support headers. Read/write.

stream.oninfo#>

当从服务器接收到信息性(1xx)头时要调用的回调。回调接收 (headers),其中 headers 是与 stream.headers 格式相同的对象。信息性头在最终响应之前发送(例如,103 Early Hints)。如果在不支持头的会话上设置,则抛出 ERR_INVALID_STATE。可读/可写。

🌐 The callback to invoke when informational (1xx) headers are received from the server. The callback receives (headers) where headers is an object in the same format as stream.headers. Informational headers are sent before the final response (e.g., 103 Early Hints). Throws ERR_INVALID_STATE if set on a session that does not support headers. Read/write.

stream.onwanttrailers#>

在应用准备好发送尾随头时要调用的回调函数。此回调是同步调用的——用户必须在此回调中调用 stream.sendTrailers()。如果在不支持头的会话上设置,则会抛出 ERR_INVALID_STATE。可读/可写。

🌐 The callback to invoke when the application is ready for trailing headers to be sent. This is called synchronously — the user must call stream.sendTrailers() within this callback. Throws ERR_INVALID_STATE if set on a session that does not support headers. Read/write.

stream.pendingTrailers#>

设置在应用请求时自动发送尾部头信息。这是 stream.onwanttrailers 回调的一种替代方法,适用于在正文完成之前已知尾部信息的情况。如果在不支持头信息的会话上设置,将抛出 ERR_INVALID_STATE。可读/可写。

🌐 Set trailing headers to be sent automatically when the application requests them. This is an alternative to the stream.onwanttrailers callback for cases where the trailers are known before the body completes. Throws ERR_INVALID_STATE if set on a session that does not support headers. Read/write.

stream.sendHeaders(headers[, options])#>

  • headers <Object> 带有字符串键和字符串或字符串数组值的头对象。伪头(:method:path 等)必须出现在常规头之前。
  • options <Object>
    • terminal <boolean> 如果 true,在头信息之后流将关闭发送(不会有正文跟随)。默认值: false
  • 返回:<boolean>

在流上发送初始或响应头。对于客户端流,这会发送请求头。对于服务器端流,这会发送响应头。如果会话不支持头,会抛出 ERR_INVALID_STATE

🌐 Sends initial or response headers on the stream. For client-side streams, this sends request headers. For server-side streams, this sends response headers. Throws ERR_INVALID_STATE if the session does not support headers.

stream.sendInformationalHeaders(headers)#>

  • headers <Object> 头部对象。必须包含 :status 并具有 1xx 值(例如,{ ':status': '103', 'link': '</style.css>; rel=preload' })。
  • 返回:<boolean>

发送信息性(1xx)响应头。仅限服务器。如果会话不支持头,则抛出 ERR_INVALID_STATE

🌐 Sends informational (1xx) response headers. Server only. Throws ERR_INVALID_STATE if the session does not support headers.

stream.sendTrailers(headers)#>

  • headers <Object> 尾部头对象。伪头部不得包含在尾部中。
  • 返回:<boolean>

在流上发送尾部头信息。必须在 stream.onwanttrailers 回调期间同步调用,或通过 stream.pendingTrailers 事先设置。如果会话不支持头信息,则抛出 ERR_INVALID_STATE

🌐 Sends trailing headers on the stream. Must be called synchronously during the stream.onwanttrailers callback, or set ahead of time via stream.pendingTrailers. Throws ERR_INVALID_STATE if the session does not support headers.

stream.priority#>

  • 类型:<Object> | <null>
    • level <string> 'high''default''low' 中的一个。
    • incremental <boolean> 是否应该将流数据与同一优先级级别的其他流交错。

流的当前优先级。如果会话不支持优先级(例如,非 HTTP/3)或流已被销毁,则返回 null。 只读。使用 stream.setPriority() 来更改优先级。

🌐 The current priority of the stream. Returns null if the session does not support priority (e.g. non-HTTP/3) or if the stream has been destroyed. Read only. Use stream.setPriority() to change the priority.

在客户端 HTTP/3 会话中,该值反映了通过 stream.setPriority() 设置的内容。在服务器端 HTTP/3 会话中,该值反映了对等方请求的优先级(例如,来自 PRIORITY_UPDATE 帧)。

🌐 On client-side HTTP/3 sessions, the value reflects what was set via stream.setPriority(). On server-side HTTP/3 sessions, the value reflects the peer's requested priority (e.g., from PRIORITY_UPDATE frames).

stream.setPriority([options])#>

  • options <Object>
    • level <string> 优先级别。可选值为 'high''default''low'默认值: 'default'
    • incremental <boolean>true 时,来自此流的数据可能与同一优先级级别的其他流的数据交错。默认: false

设置流的优先级。如果会话不支持优先级(例如非 HTTP/3),则抛出 ERR_INVALID_STATE。如果流已被销毁,则无效。

🌐 Sets the priority of the stream. Throws ERR_INVALID_STATE if the session does not support priority (e.g. non-HTTP/3). Has no effect if the stream has been destroyed.

stream[Symbol.asyncIterator]()#>

该流实现了 Symbol.asyncIterator,使其可以直接用于 for await...of 循环。每次迭代都会生成一批 Uint8Array 块。

🌐 The stream implements Symbol.asyncIterator, making it directly usable in for await...of loops. Each iteration yields a batch of Uint8Array chunks.

每个流只能获取一个异步迭代器。第二次调用会抛出 ERR_INVALID_STATE。不可读的流(仅出站的单向流或已关闭流)会返回一个立即完成的迭代器。

🌐 Only one async iterator can be obtained per stream. A second call throws ERR_INVALID_STATE. Non-readable streams (outbound-only unidirectional or closed) return an immediately-finished iterator.

for await (const chunks of stream) {
  for (const chunk of chunks) {
    // Process each Uint8Array chunk
  }
} 

与流/迭代工具兼容:

🌐 Compatible with stream/iter utilities:

import Stream from 'node:stream/iter';
const body = await Stream.bytes(stream);
const text = await Stream.text(stream);
await Stream.pipeTo(stream, someWriter); 

stream.writer#>

返回一个 Writer 对象,用于将数据分步推送到流中。Writer 实现了带有尝试同步-回退到异步模式的 stream/iter Writer 接口。

🌐 Returns a Writer object for pushing data to the stream incrementally. The Writer implements the stream/iter Writer interface with the try-sync-fallback-to-async pattern.

仅当在创建时或通过 stream.setBody() 未提供 body 源时可用。不可写的流会返回一个已关闭的 Writer。如果出站已配置,则抛出 ERR_INVALID_STATE

🌐 Only available when no body source was provided at creation time or via stream.setBody(). Non-writable streams return an already-closed Writer. Throws ERR_INVALID_STATE if the outbound is already configured.

作者有以下方法:

🌐 The Writer has the following methods:

  • writeSync(chunk) — 同步写入。如果被接受返回 true,流量控制时返回 false。在 false 上不接受数据。
  • write(chunk[, options]) — 异步写入并等待排空。options.signal 在进入时被检查,但在写入过程中未被观察。
  • writevSync(chunks) — 同步向量写入。要么全部成功,要么全部失败。
  • writev(chunks[, options]) — 异步矢量写入。
  • endSync() — 同步关闭。返回总字节数或 -1
  • end([options]) — 异步关闭。
  • fail(reason) — 出现流错误(将 RESET_STREAM 发送给对端)。当 reasonQuicError 时,其 error.errorCode 被用作生成的 RESET_STREAM 帧上的线编码;否则,线编码回退到协商的应用协议的“内部错误”代码(HTTP/3 为 H3_INTERNAL_ERROR (0x102),或原生 QUIC 为 QUIC 传输层的 INTERNAL_ERROR (0x1))。有关完全中止流的操作,并通过 STOP_SENDING 重置可读端的详情,请参见 stream.destroy()
  • desiredSize — 可用容量(字节),如果关闭/出错,则为 null

每个 writeSync() / writevSync() / write() / writev() 输入块的字节都会被复制到一个内部缓冲区,因此调用者的源缓冲区保持不变,并且可以在调用返回后立即重用或修改。希望确保源缓冲区在交出后不能被修改的调用者,可以在传递缓冲区之前自行调用 ArrayBuffer.prototype.transfer()

🌐 The bytes from each writeSync() / writevSync() / write() / writev() input chunk are copied into an internal buffer, so the caller's source buffer is unchanged and may be reused or mutated immediately after the call returns. Callers that want to ensure a source buffer cannot be mutated after handing it off can call ArrayBuffer.prototype.transfer() themselves before passing the buffer.

stream.setBody(body)#>

为流设置出站主体源。只能调用一次。 与 stream.writer 互斥。

🌐 Sets the outbound body source for the stream. Can only be called once. Mutually exclusive with stream.writer.

支持以下主体源类型:

🌐 The following body source types are supported:

  • null — 可写的一侧立即关闭(发送 FIN 且没有数据)。
  • string — 使用 UTF-8 编码并作为一个单独的数据块发送。
  • ArrayBufferSharedArrayBufferArrayBufferView —— 作为单个块发送。字节被复制到内部缓冲区,因此调用者的源缓冲区保持不变,并且可以在调用返回后立即重用或修改。希望确保在传递后源不被修改的调用者可以在传递缓冲区之前自行调用 ArrayBuffer.prototype.transfer()
  • Blob — 从Blob的底层数据队列发送。
  • <FileHandle> — 文件内容通过基于文件描述符的异步数据源读取。FileHandle 必须以读取方式打开(例如,通过 fs.promises.open(path, 'r'))。一旦作为主体传入,FileHandle 将被锁定,不能作为另一个流的主体使用。流结束时 FileHandle 会自动关闭。
  • AsyncIterableIterable —— 每个生成的块(字符串或 Uint8Array)都会以流式模式逐步写入。
  • Promise — 等待中;解析后的值将作为主体使用(遵循相同的类型规则)。

如果出站已经配置或写入器已被访问,则抛出 ERR_INVALID_STATE

🌐 Throws ERR_INVALID_STATE if the outbound is already configured or if the writer has been accessed.

stream.session#>

创建此流的会话,或者如果流已被销毁,则为 null。只读。

🌐 The session that created this stream, or null if the stream has been destroyed. Read only.

stream.stats#>

  • 类型:quic.QuicStream.Stats

当前流的数据统计。只读。

🌐 The current statistics for the stream. Read only.

类:QuicStream.Stats#>

🌐 Class: QuicStream.Stats

streamStats.ackedAt#>

streamStats.bytesReceived#>

streamStats.bytesSent#>

streamStats.createdAt#>

streamStats.destroyedAt#>

streamStats.finalSize#>

streamStats.isConnected#>

streamStats.maxOffset#>

streamStats.maxOffsetAcknowledged#>

streamStats.maxOffsetReceived#>

streamStats.openedAt#>

streamStats.receivedAt#>

类型#>

🌐 Types

类型:EndpointOptions#>

🌐 Type: EndpointOptions

在构建新的 QuicEndpoint 实例时传入的端点配置选项。

🌐 The endpoint configuration options passed when constructing a new QuicEndpoint instance.

endpointOptions.address#>

如果未指定,端点将绑定到 IPv4 的 localhost,并使用随机端口。

🌐 If not specified the endpoint will bind to IPv4 localhost on a random port.

endpointOptions.addressLRUSize#>

该端点维护一个经过验证的套接字地址的内部缓存,以优化性能。此选项设置缓存的地址的最大数量。这是一个高级选项,用户通常不需要指定。

🌐 The endpoint maintains an internal cache of validated socket addresses as a performance optimization. This option sets the maximum number of addresses that are cached. This is an advanced option that users typically won't have need to specify.

endpointOptions.disableStatelessReset#>

true 时,端点不会对来自未知连接的数据包发送无状态重置包。无状态重置允许对等方即使在服务器没有其状态时也能检测到连接已丢失。在测试中或当无状态重置在不同层处理时,禁用它们可能是有用的。

🌐 When true, the endpoint will not send stateless reset packets in response to packets from unknown connections. Stateless resets allow a peer to detect that a connection has been lost even when the server has no state for it. Disabling them may be useful in testing or when stateless resets are handled at a different layer.

endpointOptions.idleTimeout#>

在所有会话关闭且端点不再监听后,端点保持活动状态的秒数。值为 0(默认)表示端点仅在通过 endpoint.close()endpoint.destroy() 显式关闭时才会被销毁。正值会在端点空闲时启动一个空闲计时器;如果在计时器触发之前没有创建新的会话,端点会自动被销毁。这对于连接池很有用,因为端点应短暂保留以供将来的 connect() 调用重用。

🌐 The number of seconds an endpoint will remain alive after all sessions have closed and it is no longer listening. A value of 0 (default) means the endpoint is only destroyed when explicitly closed via endpoint.close() or endpoint.destroy(). A positive value starts an idle timer when the endpoint becomes idle; if no new sessions are created before the timer fires, the endpoint is automatically destroyed. This is useful for connection pooling where endpoints should linger briefly for reuse by future connect() calls.

endpointOptions.ipv6Only#>

当为 true 时,表示该端点应仅绑定到 IPv6 地址。

🌐 When true, indicates that the endpoint should bind only to IPv6 addresses.

endpointOptions.maxConnectionsPerHost#>
  • 类型:<number>
  • 默认:0(无限)

指定每个远程 IP 地址(忽略端口)允许的最大并发会话数。当达到限制时,来自同一 IP 的新连接将被 CONNECTION_REFUSED 拒绝。值为 0 表示禁用此限制。最大值为 65535

🌐 Specifies the maximum number of concurrent sessions allowed per remote IP address (ignoring port). When the limit is reached, new connections from the same IP are refused with CONNECTION_REFUSED. A value of 0 disables the limit. The maximum value is 65535.

这个限制也可以在构造后通过 endpoint.maxConnectionsPerHost 动态更改。

🌐 This limit can also be changed dynamically after construction via endpoint.maxConnectionsPerHost.

endpointOptions.maxConnectionsTotal#>
  • 类型:<number>
  • 默认:0(无限)

指定所有远程地址的最大并发会话总数。当达到限制时,新的连接会被拒绝,并显示 CONNECTION_REFUSED。值为 0 表示禁用该限制。最大值为 65535

🌐 Specifies the maximum total number of concurrent sessions across all remote addresses. When the limit is reached, new connections are refused with CONNECTION_REFUSED. A value of 0 disables the limit. The maximum value is 65535.

这个限制也可以在构造后通过 endpoint.maxConnectionsTotal 动态更改。

🌐 This limit can also be changed dynamically after construction via endpoint.maxConnectionsTotal.

endpointOptions.maxRetries#>

指定每个远程对等地址允许的最大 QUIC 重试次数。

🌐 Specifies the maximum number of QUIC retry attempts allowed per remote peer address.

endpointOptions.maxStatelessResetsPerHost#>

指定每个远程对等地址允许的最大无状态重置次数。

🌐 Specifies the maximum number of stateless resets that are allowed per remote peer address.

endpointOptions.retryTokenExpiration#>

指定 QUIC 重试令牌被视为有效的时间长度。

🌐 Specifies the length of time a QUIC retry token is considered valid.

endpointOptions.resetTokenSecret#>

指定用于生成 QUIC 重试令牌的 16 字节密钥。

🌐 Specifies the 16-byte secret used to generate QUIC retry tokens.

endpointOptions.tokenExpiration#>

指定 QUIC 令牌被视为有效的时间长度。

🌐 Specifies the length of time a QUIC token is considered valid.

endpointOptions.tokenSecret#>

指定用于生成 QUIC 令牌的 16 字节密钥。

🌐 Specifies the 16-byte secret used to generate QUIC tokens.

endpointOptions.udpReceiveBufferSize#>
endpointOptions.udpSendBufferSize#>
endpointOptions.udpTTL#>
endpointOptions.validateAddress#>

当为true时,要求端点在建立新连接时使用重试数据包来验证对等方地址。

🌐 When true, requires that the endpoint validate peer addresses using retry packets while establishing a new connection.

类型:SessionOptions#>

🌐 Type: SessionOptions

sessionOptions.alpn#>
  • 类型:<string> (客户端) | 字符串数组 (服务器)

ALPN(应用层协议协商)标识符。

🌐 The ALPN (Application-Layer Protocol Negotiation) identifier(s).

对于客户端会话,这是一个指定客户端想要使用的协议的单个字符串(例如 'h3')。

🌐 For client sessions, this is a single string specifying the protocol the client wants to use (e.g. 'h3').

对于 服务器 会话,这是服务器支持的协议名称数组,按照优先顺序排列(例如 ['h3', 'h3-29'])。在 TLS 握手期间,服务器会从其列表中选择客户端也支持的第一个协议。

🌐 For server sessions, this is an array of protocol names in preference order that the server supports (e.g. ['h3', 'h3-29']). During the TLS handshake, the server selects the first protocol from its list that the client also supports.

协商的 ALPN 决定会话使用哪种应用实现。'h3''h3-*' 变体选择 HTTP/3 应用;所有其他值选择默认应用。

🌐 The negotiated ALPN determines which Application implementation is used for the session. 'h3' and 'h3-*' variants select the HTTP/3 application; all other values select the default application.

默认:'h3'

🌐 Default: 'h3'

sessionOptions.application#>

HTTP/3 应用特定选项。仅在协商的 ALPN 选择 HTTP/3 应用('h3')时适用。

🌐 HTTP/3 application-specific options. These only apply when the negotiated ALPN selects the HTTP/3 application ('h3').

  • maxHeaderPairs <number> 每个头块接收的最大头名称-值对数量。超过此限制的头将被静默丢弃。默认值: 128
  • maxHeaderLength <number> 每个头块中所有头名称和值总和的最大字节长度。会将导致总长度超过此限制的头静默丢弃。默认值:8192
  • maxFieldSectionSize <number> 压缩头字段部分的最大尺寸(QPACK)。0 表示无限制。默认值: 0
  • qpackMaxDTableCapacity <number> QPACK 动态表容量(字节)。设置为 0 可禁用动态表。默认值: 4096
  • qpackEncoderMaxDTableCapacity <number> QPACK 编码器最大动态表容量。默认值: 4096
  • qpackBlockedStreams <number> 等待 QPACK 动态表更新时可以被阻塞的最大流数。默认值: 100
  • enableConnectProtocol <boolean> 启用扩展 CONNECT 协议 (RFC 9220)。默认值:false
  • enableDatagrams <boolean> 启用 HTTP/3 数据报(RFC 9297)。默认值:false
const { listen } = await import('node:quic');

await listen((session) => { /* ... */ }, {
  application: {
    maxHeaderPairs: 64,
    qpackMaxDTableCapacity: 8192,
    enableDatagrams: true,
  },
  // ... other session options
}); 

sessionOptions.ca(仅客户端)#>

🌐 sessionOptions.ca (client only)

用于客户端会话的 CA 证书。对于服务器会话,CA 证书在 sessionOptions.sni 映射中按身份指定。

🌐 The CA certificates to use for client sessions. For server sessions, CA certificates are specified per-identity in the sessionOptions.sni map.

sessionOptions.cc#>

指定将使用的拥塞控制算法。必须设置为 'reno''cubic''bbr' 中的一个。

🌐 Specifies the congestion control algorithm that will be used. Must be set to one of either 'reno', 'cubic', or 'bbr'.

这是一个高级选项,用户通常不需要指定。

🌐 This is an advanced option that users typically won't have need to specify.

sessionOptions.certs(仅限客户端)#>

🌐 sessionOptions.certs (client only)

用于客户端会话的 TLS 证书。对于服务器会话,证书在 sessionOptions.sni 映射中按身份指定。

🌐 The TLS certificates to use for client sessions. For server sessions, certificates are specified per-identity in the sessionOptions.sni map.

sessionOptions.ciphers#>

支持的 TLS 1.3 密码算法列表。

🌐 The list of supported TLS 1.3 cipher algorithms.

sessionOptions.crl(仅客户端)#>

🌐 sessionOptions.crl (client only)

用于客户端会话的 CRL。对于服务器会话,CRL 在 sessionOptions.sni 映射中按身份指定。

🌐 The CRL to use for client sessions. For server sessions, CRLs are specified per-identity in the sessionOptions.sni map.

sessionOptions.enableEarlyData#>

true 时,为此会话启用 TLS 0-RTT 早期数据。早期数据允许客户端在 TLS 握手完成之前发送应用数据,当可用有效会话票据时,可以减少重新连接的延迟。设置为 false 以禁用早期数据支持。

🌐 When true, enables TLS 0-RTT early data for this session. Early data allows the client to send application data before the TLS handshake completes, reducing latency on reconnection when a valid session ticket is available. Set to false to disable early data support.

sessionOptions.groups#>

支持的 TLS 1.3 密码组列表。

🌐 The list of supported TLS 1.3 cipher groups.

sessionOptions.keylog#>

true 时,为会话启用 TLS 密钥记录。密钥材料会通过 NSS 密钥日志格式 中的 session.onkeylog 回调传递。每次回调调用会接收一行密钥材料。输出可与 Wireshark 等工具一起用于解密捕获的 QUIC 流量。

🌐 When true, enables TLS key logging for the session. Key material is delivered to the session.onkeylog callback in NSS Key Log Format. Each callback invocation receives a single line of key material. The output can be used with tools such as Wireshark to decrypt captured QUIC traffic.

sessionOptions.keys(仅限客户端)#>

🌐 sessionOptions.keys (client only)

用于客户端会话的 TLS 加密密钥。对于服务器会话,密钥在 sessionOptions.sni 映射中按身份指定。

🌐 The TLS crypto keys to use for client sessions. For server sessions, keys are specified per-identity in the sessionOptions.sni map.

sessionOptions.maxPayloadSize#>

指定最大 UDP 数据包有效负载大小。

🌐 Specifies the maximum UDP packet payload size.

sessionOptions.maxStreamWindow#>

指定最大流流量控制窗口大小。

🌐 Specifies the maximum stream flow-control window size.

sessionOptions.maxWindow#>

指定会话流控制窗口的最大大小。

🌐 Specifies the maximum session flow-control window size.

sessionOptions.minVersion#>

允许的最低 QUIC 版本号。这是一个高级选项,普通用户通常不需要指定。

🌐 The minimum QUIC version number to allow. This is an advanced option that users typically won't have need to specify.

sessionOptions.preferredAddressPolicy#>
  • 类型:<string> 'use''ignore''default' 之一。

当远程端广告首选地址时,此选项指定是使用它还是忽略它。

🌐 When the remote peer advertises a preferred address, this option specifies whether to use it or ignore it.

sessionOptions.qlog#>

true 时,为会话启用 q日志 诊断输出。Qlog 数据以 JSON-序列 格式的文本块形式传送到 session.onqlog 回调。输出可以使用诸如 qvis 的 qlog 可视化工具进行分析。

🌐 When true, enables qlog diagnostic output for the session. Qlog data is delivered to the session.onqlog callback as chunks of JSON-SEQ formatted text. The output can be analyzed with qlog visualization tools such as qvis.

sessionOptions.sessionTicket#>
sessionOptions.datagramDropPolicy#>
  • 类型:<string>
  • 默认: 'drop-oldest'

控制在待处理数据报队列(大小由 session.maxPendingDatagrams 决定)已满时丢弃哪个数据报。必须是 'drop-oldest'(丢弃最旧的已排队数据报以腾出空间)或 'drop-newest'(拒绝接收的数据报)。丢弃的数据报将通过 ondatagramstatus 回调报告为丢失。

🌐 Controls which datagram to drop when the pending datagram queue (sized by session.maxPendingDatagrams) is full. Must be one of 'drop-oldest' (discard the oldest queued datagram to make room) or 'drop-newest' (reject the incoming datagram). Dropped datagrams are reported as lost via the ondatagramstatus callback.

此选项在会话创建后不可更改。

🌐 This option is immutable after session creation.

sessionOptions.maxDatagramSendAttempts#>

SendPendingData 循环次数是数据报在未被发送之前可以存活的最大次数。一旦由于拥塞控制或数据包大小限制导致数据报无法发送,它将保持在队列中,并且尝试计数器会增加。一旦达到上限,数据报将被丢弃,并通过 ondatagramstatus 回调报告为 'abandoned'。有效范围:1255

🌐 The maximum number of SendPendingData cycles a datagram can survive without being sent before it is abandoned. When a datagram cannot be sent due to congestion control or packet size constraints, it remains in the queue and the attempt counter increments. Once the limit is reached, the datagram is dropped and reported as 'abandoned' via the ondatagramstatus callback. Valid range: 1 to 255.

sessionOptions.drainingPeriodMultiplier#>

在收到来自对等方的 CONNECTION_CLOSE 帧后,一个应用于探测超时 (PTO) 的乘数,用于计算排空期的持续时间。RFC 9000 第 10.2 节要求排空期至少持续当前 PTO 的三倍。有效范围是 3255。低于 3 的值会被钳制为 3

🌐 A multiplier applied to the Probe Timeout (PTO) to compute the draining period duration after receiving a CONNECTION_CLOSE frame from the peer. RFC 9000 Section 10.2 requires the draining period to persist for at least three times the current PTO. The valid range is 3 to 255. Values below 3 are clamped to 3.

sessionOptions.handshakeTimeout#>

指定 TLS 握手允许完成的最长毫秒数,超过此时间将超时。

🌐 Specifies the maximum number of milliseconds a TLS handshake is permitted to take to complete before timing out.

sessionOptions.keepAlive#>

指定以毫秒为单位的保持活动超时。当设置为非零值时,会自动发送 PING 帧以在空闲超时触发前保持连接活动。该值应小于有效的空闲超时(maxIdleTimeout 传输参数),以便有用。

🌐 Specifies the keep-alive timeout in milliseconds. When set to a non-zero value, PING frames will be sent automatically to keep the connection alive before the idle timeout fires. The value should be less than the effective idle timeout (maxIdleTimeout transport parameter) to be useful.

sessionOptions.servername(仅客户端)#>

🌐 sessionOptions.servername (client only)

要定位的对等服务器名称(SNI)。默认值为 'localhost'

🌐 The peer server name to target (SNI). Defaults to 'localhost'.

sessionOptions.sni(仅限服务器)#>

🌐 sessionOptions.sni (server only)

一个将主机名映射到用于服务器名称指示 (SNI) 支持的 TLS 身份选项的对象。这对于服务器会话是必需的,并且必须至少包含一个条目。特殊键 '*' 指定在没有其他主机名匹配时使用的可选默认/备用身份。如果未提供通配符条目,具有无法识别服务器名称的连接将被 TLS unrecognized_name 警报拒绝。每个条目可以包含:

🌐 An object mapping host names to TLS identity options for Server Name Indication (SNI) support. This is required for server sessions and must contain at least one entry. The special key '*' specifies the optional default/fallback identity used when no other host name matches. If no wildcard entry is provided, connections with unrecognized server names will be rejected with a TLS unrecognized_name alert. Each entry may contain:

  • keys <KeyObject> | <KeyObject[]> TLS 私钥。必需。
  • certs <ArrayBuffer> | <ArrayBufferView> | <ArrayBuffer[]> | <ArrayBufferView[]> TLS 证书。必需。 可选的证书吊销列表。
  • verifyPrivateKey <boolean> 验证私钥。默认值:false
  • port <number> 在 ORIGIN 帧中为此主机名广告的端口(RFC 9412)。默认值:443。仅用于 HTTP/3 会话。
  • authoritative <boolean> 是否在 ORIGIN 帧中包含此主机名。默认值: true。设置为 false 可将主机名排除在 ORIGIN 广告之外。通配符('*')条目无论此设置如何,总是被排除。
const endpoint = await listen(callback, {
  sni: {
    '*': { keys: [defaultKey], certs: [defaultCert] },
    'api.example.com': { keys: [apiKey], certs: [apiCert], port: 8443 },
    'www.example.com': { keys: [wwwKey], certs: [wwwCert], ca: [customCA] },
    'internal.example.com': { keys: [intKey], certs: [intCert], authoritative: false },
  },
}); 

共享的 TLS 选项(例如 ciphersgroupskeylogverifyClient)在会话选项的顶层指定,并适用于所有身份。每个 SNI 条目仅覆盖每个身份的证书字段。

🌐 Shared TLS options (such as ciphers, groups, keylog, and verifyClient) are specified at the top level of the session options and apply to all identities. Each SNI entry overrides only the per-identity certificate fields.

SNI 映射可以在运行时使用 endpoint.setSNIContexts() 替换,该操作会以原子方式为新的会话交换映射,而现有会话则继续使用它们的原始身份。

🌐 The SNI map can be replaced at runtime using endpoint.setSNIContexts(), which atomically swaps the map for new sessions while existing sessions continue to use their original identity.

sessionOptions.tlsTrace#>

如果启用 TLS 跟踪输出,则为 True。

🌐 True to enable TLS tracing output.

sessionOptions.token(仅限客户端)#>

🌐 sessionOptions.token (client only)

先前通过 session.onnewtoken 回调从服务器接收的不透明地址验证令牌。在重新连接时提供有效的令牌可以让客户端跳过服务器的地址验证,从而减少握手延迟。

🌐 An opaque address validation token previously received from the server via the session.onnewtoken callback. Providing a valid token on reconnection allows the client to skip the server's address validation, reducing handshake latency.

sessionOptions.transportParams#>
  • 类型:quic.TransportParams

用于会话的 QUIC 传输参数。

🌐 The QUIC transport parameters to use for the session.

sessionOptions.unacknowledgedPacketThreshold#>

指定会话应允许的最大未确认数据包数。

🌐 Specifies the maximum number of unacknowledged packets a session should allow.

sessionOptions.rejectUnauthorized#>

如果 true,对等证书会根据提供的 CA 列表进行验证。如果验证失败,将会发出错误;可以通过握手回调中的 validationErrorReasonvalidationErrorCode 字段检查该错误。如果 false,对等证书验证错误将被忽略。

🌐 If true, the peer certificate is verified against the list of supplied CAs. An error is emitted if verification fails; the error can be inspected via the validationErrorReason and validationErrorCode fields in the handshake callback. If false, peer certificate verification errors are ignored.

sessionOptions.reuseEndpoint#>

true(默认值)时,connect() 将尝试重用现有端点,而不是为每个会话创建新的端点。这提供了连接池行为——多个会话可以共享单个 UDP 套接字。重用逻辑不会返回在与连接目标相同地址上监听的端点(以防止 CID 路由冲突)。

🌐 When true (the default), connect() will attempt to reuse an existing endpoint rather than creating a new one for each session. This provides connection pooling behavior — multiple sessions can share a single UDP socket. The reuse logic will not return an endpoint that is listening on the same address as the connect target (to prevent CID routing conflicts).

设置为 false 以强制为会话创建一个新的端点。当需要端点隔离时(例如,测试无状态重置行为时源端口身份很重要)这很有用。

🌐 Set to false to force creation of a new endpoint for the session. This is useful when endpoint isolation is required (e.g., testing stateless reset behavior where source port identity matters).

sessionOptions.verifyClient#>

如果要求验证 TLS 客户端证书,则为 True。

🌐 True to require verification of TLS client certificate.

sessionOptions.verifyPrivateKey(仅客户端)#>

🌐 sessionOptions.verifyPrivateKey (client only)

确实需要对客户端会话进行私钥验证。对于服务器会话,此选项在 sessionOptions.sni 映射中按身份指定。

🌐 True to require private key verification for client sessions. For server sessions, this option is specified per-identity in the sessionOptions.sni map.

sessionOptions.version#>

要使用的 QUIC 版本号。这是一个高级选项,普通用户通常不需要指定。

🌐 The QUIC version number to use. This is an advanced option that users typically won't have need to specify.

类型:TransportParams#>

🌐 Type: TransportParams

transportParams.preferredAddressIpv4#>
transportParams.preferredAddressIpv6#>
transportParams.initialMaxStreamDataBidiLocal#>
transportParams.initialMaxStreamDataBidiRemote#>
transportParams.initialMaxStreamDataUni#>
transportParams.initialMaxData#>
transportParams.initialMaxStreamsBidi#>
transportParams.initialMaxStreamsUni#>
transportParams.maxIdleTimeout#>
transportParams.activeConnectionIDLimit#>
transportParams.ackDelayExponent#>
transportParams.maxAckDelay#>
transportParams.maxDatagramFrameSize#>

此端点愿意接收的 DATAGRAM 帧有效负载的最大字节数。设置为 0 以禁用数据报支持。对等方不会发送超过此值的数据报。实际上可以发送的数据报的最大大小由对等方的 maxDatagramFrameSize 决定,而不是此端点的值。

🌐 The maximum size in bytes of a DATAGRAM frame payload that this endpoint is willing to receive. Set to 0 to disable datagram support. The peer will not send datagrams larger than this value. The actual maximum size of a datagram that can be sent is determined by the peer's maxDatagramFrameSize, not this endpoint's value.

回调#>

🌐 Callbacks

回调错误处理#>

🌐 Callback error handling

所有会话和流回调可以是同步函数或异步函数。如果回调同步抛出错误或返回被拒绝的 Promise,该错误将被捕获,并且拥有该回调的会话或流将因该错误而被销毁:

🌐 All session and stream callbacks may be synchronous functions or async functions. If a callback throws synchronously or returns a promise that rejects, the error is caught and the owning session or stream is destroyed with that error:

  • 流回调(onblockedonresetonheadersontrailersoninfoonwanttrailers):流已被销毁。
  • 会话回调(onstreamondatagramondatagramstatusonpathvalidationonsessionticketonnewtokenonversionnegotiationonoriginongoawayonhandshakeonkeylogonqlog):会话会被销毁,同时其所有流也会被销毁。

在销毁之前,将调用可选的 session.onerrorstream.onerror 回调(如果已设置),让应用有机会观察或记录错误。session.closedstream.closed 的 promise 将因该错误而被拒绝。

🌐 Before destruction, the optional session.onerror or stream.onerror callback is invoked (if set), giving the application a chance to observe or log the error. The session.closed or stream.closed promise will reject with the error.

如果 onerror 回调本身抛出异常或返回一个被拒绝的 Promise,onerror 的错误将作为未捕获的异常出现。

🌐 If the onerror callback itself throws or returns a promise that rejects, the error from onerror is surfaced as an uncaught exception.

回调:OnSessionCallback#>

🌐 Callback: OnSessionCallback

  • this quic.QuicEndpoint
  • session quic.QuicSession

当远程对等方发起新会话时调用的回调函数。

🌐 The callback function that is invoked when a new session is initiated by a remote peer.

回调:OnStreamCallback#>

🌐 Callback: OnStreamCallback

  • this quic.QuicSession
  • stream quic.QuicStream

回调:OnDatagramCallback#>

🌐 Callback: OnDatagramCallback

回调:OnDatagramStatusCallback#>

🌐 Callback: OnDatagramStatusCallback

  • this quic.QuicSession
  • id <bigint>
  • status <string> 'acknowledged''lost''abandoned' 之一。'acknowledged' 表示对等方确认收到。'lost' 表示数据报已发送,但网络丢失了它。'abandoned' 表示数据报从未在网络上发送(由于队列溢出、超出发送尝试次数限制或帧大小被拒绝而丢弃)。

回调:OnPathValidationCallback#>

🌐 Callback: OnPathValidationCallback

  • this quic.QuicSession
  • result <string> 以下三个之一:'success''failure''aborted'
  • newLocalAddress <net.SocketAddress> 已验证路径的本地地址。
  • newRemoteAddress <net.SocketAddress> 已验证路径的远程地址。
  • oldLocalAddress <net.SocketAddress> | <null> 上一路径的本地地址,或者如果这是第一次路径验证则为 null(例如,从客户端的角度来看,首选地址迁移)。
  • oldRemoteAddress <net.SocketAddress> | <null> 先前路径的远程地址,或 null
  • preferredAddress <boolean> true 如果路径验证是由客户端的首选地址迁移触发的。undefined 在服务器端。

回调:OnSessionTicketCallback#>

🌐 Callback: OnSessionTicketCallback

回调:OnVersionNegotiationCallback#>

🌐 Callback: OnVersionNegotiationCallback

  • this quic.QuicSession
  • version <number> 为此会话配置的 QUIC 版本(服务器不支持的版本)。
  • requestedVersions <number[]> 服务器在版本协商数据包中宣告的版本。这些是服务器支持的版本。
  • supportedVersions <number[]> 本地支持的版本,以两个元素的数组 [minVersion, maxVersion] 表示。

当服务器以版本协商包响应客户端的初始数据包时调用,表示客户端使用的版本不被支持。此回调返回后,会立即销毁会话。

🌐 Called when the server responds to the client's Initial packet with a Version Negotiation packet, indicating that the version used by the client is not supported. The session is always destroyed immediately after this callback returns.

回调:OnHandshakeCallback#>

🌐 Callback: OnHandshakeCallback

  • this quic.QuicSession
  • info <Object>session.opened 解析的对象相同。
    • local <net.SocketAddress> 本地套接字地址。
    • remote <net.SocketAddress> 远程套接字地址。
    • servername <string> 在握手过程中协商的 SNI 服务器名称。
    • protocol <string> 在握手期间协商的 ALPN 协议。
    • cipher <string> 协商的 TLS 密码套件的名称。
    • cipherVersion <string> 加密套件的 TLS 协议版本。
    • validationErrorReason <string> 如果证书验证失败,返回原因字符串。如果验证成功,则返回空字符串。
    • validationErrorCode <number> 如果证书验证失败,则显示错误代码。如果验证成功,则为 0
    • earlyDataAttempted <boolean> 是否尝试了 0-RTT 早期数据。
    • earlyDataAccepted <boolean> 是否接受了 0-RTT 早期数据。

回调:OnNewTokenCallback#>

🌐 Callback: OnNewTokenCallback

  • this quic.QuicSession
  • token <Buffer> NEW_TOKEN 令牌数据。
  • address SocketAddress 令牌关联的远程地址。

回调:OnOriginCallback#>

🌐 Callback: OnOriginCallback

  • this quic.QuicSession
  • origins <string[]> 服务器具有权威的来源列表。

回调:OnKeylogCallback#>

🌐 Callback: OnKeylogCallback

在 TLS 密钥材料可用时调用。仅当 sessionOptions.keylogtrue 时触发。在 TLS 1.3 握手过程中会发出多行,每行包含一个秘密标签、客户端随机数和秘密值。

🌐 Called when TLS key material is available. Only fires when sessionOptions.keylog is true. Multiple lines are emitted during the TLS 1.3 handshake, each containing a secret label, the client random, and the secret value.

回调:OnQlogCallback#>

🌐 Callback: OnQlogCallback

当 qlog 诊断数据可用时调用。仅在 sessionOptions.qlogtrue 时触发。data 块应按顺序连接以生成完整的 qlog 输出。当 fintrue 时,将不再发出更多块,连接后的结果是完整的 JSON-SEQ 文档。

🌐 Called when qlog diagnostic data is available. Only fires when sessionOptions.qlog is true. The data chunks should be concatenated in order to produce the complete qlog output. When fin is true, no more chunks will be emitted and the concatenated result is a complete JSON-SEQ document.

回调:OnBlockedCallback#>

🌐 Callback: OnBlockedCallback

  • this quic.QuicStream

回调:OnStreamErrorCallback#>

🌐 Callback: OnStreamErrorCallback

  • this quic.QuicStream
  • error <any>

回调:OnHeadersCallback#>

🌐 Callback: OnHeadersCallback

  • this quic.QuicStream
  • headers <Object> 带有小写字符串键和字符串或字符串数组值的头对象。

在接收到初始请求或响应头时调用。对于 HTTP/3,这会在服务器端传递请求伪头,在客户端传递响应头。

🌐 Called when initial request or response headers are received. For HTTP/3, this delivers request pseudo-headers on the server and response headers on the client.

回调:OnTrailersCallback#>

🌐 Callback: OnTrailersCallback

  • this quic.QuicStream
  • trailers <Object> 尾随头对象。

当从对端接收到尾部头时调用。

🌐 Called when trailing headers are received from the peer.

回调:OnInfoCallback#>

🌐 Callback: OnInfoCallback

  • this quic.QuicStream
  • headers <Object> 信息头对象。

当从服务器接收到信息性(1xx)头时调用(例如,103 早期提示)。

🌐 Called when informational (1xx) headers are received from the server (e.g., 103 Early Hints).

HTTP/3 支持#>

🌐 HTTP/3 support

当协商的 ALPN 标识符为 'h3'(或某个 'h3-*' 草案变体之一)时,QUIC 会话会运行由 nghttp3 支持的 HTTP/3 应用。'h3'quic.connect()quic.listen() 的默认 ALPN,因此除非你明确选择不同的 ALPN,否则你得到的就是 HTTP/3。

🌐 When the negotiated ALPN identifier is 'h3' (or one of the 'h3-*' draft variants), the QUIC session runs the HTTP/3 application backed by nghttp3. 'h3' is the default ALPN for quic.connect() and quic.listen(), so HTTP/3 is what you get unless you select a different ALPN explicitly.

选择 HTTP/3 应用可以启用许多非 HTTP/3 应用无法使用的流级和会话级功能:

🌐 Selecting the HTTP/3 application enables a number of stream- and session-level capabilities that are not available to non-HTTP/3 applications:

最小化 HTTP/3 客户端#>

🌐 Minimal HTTP/3 client

import { connect } from 'node:quic';
import process from 'node:process';

const session = await connect('example.com:443', {
  // ALPN defaults to 'h3'.
  servername: 'example.com',
});
await session.opened;

const stream = await session.createBidirectionalStream({
  headers: {
    ':method': 'GET',
    ':path': '/',
    ':scheme': 'https',
    ':authority': 'example.com',
  },
  onheaders(headers) {
    console.log('status:', headers[':status']);
  },
});

const decoder = new TextDecoder();
for await (const chunks of stream) {
  for (const chunk of chunks) {
    process.stdout.write(decoder.decode(chunk, { stream: true }));
  }
}

await session.close(); 

需要注意的几点:

🌐 A few things to note:

  • session.createBidirectionalStream({ headers }) 会在未提供 body 时自动将 HEADERS 帧标记为终止 —— 请求是 HEADERS,后跟 END_STREAM
  • onheaders 回调接收响应伪头和常规头,它们都在一个具有小写字符串键的对象中。回调返回后,通过 stream.headers 也可以访问同一个对象。
  • 读取 for await (const chunks of stream) 会消耗响应体。每次迭代会产生一个 Uint8Array[] 的块批次。
  • HTTP 语义辅助工具(URL 解析、方法/状态验证、重定向、内容协商等)故意没有内置。调用者负责除传输框架之外的任何 HTTP 级别处理。

最小化 HTTP/3 服务器#>

🌐 Minimal HTTP/3 server

import { listen } from 'node:quic';

const encoder = new TextEncoder();

const endpoint = await listen((session) => {
  // The session.onstream callback fires for each new client-initiated stream.
}, {
  sni: { '*': { keys: [defaultKey], certs: [defaultCert] } },
  // ALPN defaults to 'h3'.
  onheaders(headers) {
    // `this` is the QuicStream. Pseudo-headers are available on the
    // request header block (`:method`, `:path`, `:scheme`,
    // `:authority`).
    if (headers[':path'] === '/health') {
      this.sendHeaders({ ':status': '200', 'content-type': 'text/plain' });
      const w = this.writer;
      w.writeSync(encoder.encode('ok\n'));
      w.endSync();
    } else {
      this.sendHeaders({ ':status': '404' }, { terminal: true });
    }
  },
});

console.log('listening on', endpoint.address); 

服务器端备注:

🌐 Server-side notes:

  • onheaders 设置在 listen() 级别会将其应用到每一个传入流(它在 onstream 触发之前就已连接)。在 onstream 内部设置它对于 HTTP/3 来说太晚,因为请求 HEADERS 帧是到达流上的第一件事。
  • this.sendHeaders(headers, { terminal: true }) 将响应 HEADERS 帧标记为终止帧(后面没有正文)。
  • 对于主体响应,先发送头部,然后写入 this.writer 并调用 endSync() 来发送正文并干净地关闭流。

未实现的内容#>

🌐 What is not implemented

  • 服务器推送PUSH_PROMISE 及相关的推送流机制尚未实现,也不在近期的开发计划中。服务器推送在实际中的部署有限,大多数使用案例更适合使用早期提示(103)或由客户端直接获取。
  • WebTransport / 扩展 CONNECT 辅助功能 — 可以协商 SETTINGS_ENABLE_CONNECT_PROTOCOL 设置,但没有内置支持 :protocol 伪头部、WebTransport 数据报复用或封装帧。
  • 更高级的 HTTP 语义 — 没有内置的请求/响应路由、URL 解析、内容编码协商、主体类型强制转换、重定向跟随或 Cookie 处理。这些特性故意留给基于 node:quic 构建的高级库来实现。

性能衡量#>

🌐 Performance measurement

QUIC 会话、流和端点会发出 PerformanceEntry 对象,entryType 设置为 'quic'。这些条目仅在 PerformanceObserver 正在观察 'quic' 条目类型时创建,确保在未使用时零开销。

🌐 QUIC sessions, streams, and endpoints emit PerformanceEntry objects with entryType set to 'quic'. These entries are only created when a PerformanceObserver is observing the 'quic' entry type, ensuring zero overhead when not in use.

每个条目提供:

🌐 Each entry provides:

  • name <string> 'QuicEndpoint''QuicSession''QuicStream' 中的一个。
  • entryType <string> 总是 'quic'
  • startTime <number> 对象创建时的高分辨率时间戳(毫秒)。
  • duration <number> 从创建到销毁的生命周期(以毫秒为单位)。
  • detail <Object> 条目特定的元数据(见下文)。

QuicEndpoint 条目#>

🌐 QuicEndpoint entries

  • detail.stats QuicEndpointStats 端点的统计对象(在销毁时被冻结)。

QuicSession 条目#>

🌐 QuicSession entries

  • detail.stats QuicSessionStats 会话的统计对象(在销毁时冻结)。包括发送/接收的字节数、往返时间测量、拥塞窗口、数据包计数等。
  • detail.handshake <Object> | <undefined> 与时序相关的握手元数据,或者如果握手在销毁前未完成,则为 undefined
    • servername <string> 协商的 SNI 服务器名称。
    • protocol <string> 协商的 ALPN 协议。
    • earlyDataAttempted <boolean> 是否尝试了 0-RTT 早期数据。
    • earlyDataAccepted <boolean> 是否接受了 0-RTT 早期数据。
  • detail.path <Object> | <undefined> 会话的网络路径,如果尚未建立,则为 undefined

QuicStream 条目#>

🌐 QuicStream entries

  • detail.stats QuicStreamStats 流的统计对象(在销毁时被冻结)。包括发送/接收的字节、时间戳和偏移跟踪。
  • detail.direction <string> 'bidi''uni'

示例#>

🌐 Example

import { PerformanceObserver } from 'node:perf_hooks';

const obs = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log(`${entry.name}: ${entry.duration.toFixed(1)}ms`);
    if (entry.name === 'QuicSession') {
      const { stats, handshake } = entry.detail;
      console.log(`  protocol: ${handshake?.protocol}`);
      console.log(`  bytes sent: ${stats.bytesSent}`);
      console.log(`  smoothed RTT: ${stats.smoothedRtt}ns`);
    }
  }
});
obs.observe({ entryTypes: ['quic'] }); 

诊断通道#>

🌐 Diagnostic Channels

通道:quic.endpoint.created#>

🌐 Channel: quic.endpoint.created

  • endpoint quic.QuicEndpoint
  • config quic.EndpointOptions

在创建新端点时发布。

🌐 Published when a new endpoint is created.

通道:quic.endpoint.listen#>

🌐 Channel: quic.endpoint.listen

  • endpoint quic.QuicEndpoint
  • options quic.SessionOptions

当端点开始监听传入连接时发布。

🌐 Published when an endpoint begins listening for incoming connections.

通道:quic.endpoint.connect#>

🌐 Channel: quic.endpoint.connect

  • endpoint quic.QuicEndpoint
  • address <net.SocketAddress> 目标服务器地址。
  • options quic.SessionOptions

quic.connect() 即将创建客户端会话时发布。在 ngtcp2 连接建立之前触发,允许诊断订阅者观察连接意图。

🌐 Published when quic.connect() is about to create a client session. Fires before the ngtcp2 connection is established, allowing diagnostic subscribers to observe the connection intent.

通道:quic.endpoint.closing#>

🌐 Channel: quic.endpoint.closing

  • endpoint quic.QuicEndpoint
  • hasPendingError <boolean>

当端点开始优雅关闭时发布。

🌐 Published when an endpoint begins gracefully closing.

通道:quic.endpoint.closed#>

🌐 Channel: quic.endpoint.closed

  • endpoint quic.QuicEndpoint
  • stats quic.QuicEndpoint.Stats 最终端点统计。

在端点关闭并被销毁后发布。

🌐 Published when an endpoint has finished closing and is destroyed.

通道:quic.endpoint.error#>

🌐 Channel: quic.endpoint.error

  • endpoint quic.QuicEndpoint
  • error <any>

当端点遇到导致其关闭的错误时发布。

🌐 Published when an endpoint encounters an error that causes it to close.

通道:quic.endpoint.busy.change#>

🌐 Channel: quic.endpoint.busy.change

在端点的忙碌状态发生变化时发布。

🌐 Published when an endpoint's busy state changes.

通道:quic.session.created.client#>

🌐 Channel: quic.session.created.client

  • endpoint quic.QuicEndpoint
  • session quic.QuicSession
  • address <net.SocketAddress> 远程服务器地址。
  • options quic.SessionOptions

在创建由客户端发起的会话时发布。

🌐 Published when a client-initiated session is created.

通道:quic.session.created.server#>

🌐 Channel: quic.session.created.server

当为传入连接创建服务器端会话时发布。

🌐 Published when a server-side session is created for an incoming connection.

通道:quic.session.open.stream#>

🌐 Channel: quic.session.open.stream

  • stream quic.QuicStream
  • session quic.QuicSession
  • direction <string> 'bidi''uni'

在本地发起的流被打开时发布。

🌐 Published when a locally-initiated stream is opened.

通道:quic.session.received.stream#>

🌐 Channel: quic.session.received.stream

  • stream quic.QuicStream
  • session quic.QuicSession
  • direction <string> 'bidi''uni'

在接收到远程启动的流时发布。

🌐 Published when a remotely-initiated stream is received.

通道:quic.session.send.datagram#>

🌐 Channel: quic.session.send.datagram

  • id <bigint> 数据报标识符。
  • length <number> 数据报有效载荷大小(以字节为单位)。
  • session quic.QuicSession

当数据报排队发送时发布。

🌐 Published when a datagram is queued for sending.

通道:quic.session.update.key#>

🌐 Channel: quic.session.update.key

  • session quic.QuicSession

在启动 TLS 密钥更新时发布。

🌐 Published when a TLS key update is initiated.

通道:quic.session.closing#>

🌐 Channel: quic.session.closing

  • session quic.QuicSession

在会话开始优雅关闭时发布(包括从对等方收到 GOAWAY 帧时)。

🌐 Published when a session begins gracefully closing (including when a GOAWAY frame is received from the peer).

通道:quic.session.closed#>

🌐 Channel: quic.session.closed

  • session quic.QuicSession
  • error <any> 导致关闭的错误,或者如果没有错误则为 undefined
  • stats quic.QuicSession.Stats 最终会话统计。

在会话被销毁时发布。stats 对象是销毁时最终统计数据的快照。

🌐 Published when a session is destroyed. The stats object is a snapshot of the final statistics at the time of destruction.

通道:quic.session.error#>

🌐 Channel: quic.session.error

  • session quic.QuicSession
  • error <any> 导致会话被销毁的错误。

当会话因错误而被销毁时发布。在 onerror 回调触发之前以及流被销毁之前触发。与 quic.session.closed(在正常关闭和错误关闭时都会触发)不同,该通道仅在出现错误时触发,因此适合仅用于错误提示。

🌐 Published when a session is destroyed due to an error. Fires before the onerror callback and before streams are torn down. Unlike quic.session.closed (which fires for both clean and error closes), this channel fires only when an error is present, making it suitable for error-only alerting.

通道:quic.session.receive.datagram#>

🌐 Channel: quic.session.receive.datagram

  • length <number> 数据报有效载荷大小(以字节为单位)。
  • early <boolean> 数据报是否作为 0-RTT 提前数据接收。
  • session quic.QuicSession

当从远程对等方接收到数据报时发布。

🌐 Published when a datagram is received from the remote peer.

通道:quic.session.receive.datagram.status#>

🌐 Channel: quic.session.receive.datagram.status

  • id <bigint> 数据报标识符。
  • status <string> 'acknowledged''lost''abandoned' 中的一个。
  • session quic.QuicSession

在已发送的数据报的传送状态更新时发布。

🌐 Published when the delivery status of a sent datagram is updated.

通道:quic.session.path.validation#>

🌐 Channel: quic.session.path.validation

在路径验证尝试完成时发布。

🌐 Published when a path validation attempt completes.

通道:quic.session.new.token#>

🌐 Channel: quic.session.new.token

当客户端会话从服务器接收到 NEW_TOKEN 帧时发布。

🌐 Published when a client session receives a NEW_TOKEN frame from the server.

通道:quic.session.ticket#>

🌐 Channel: quic.session.ticket

  • ticket <Object> 不透明的会话票据。
  • session quic.QuicSession

在收到新的 TLS 会话票证时发布。

🌐 Published when a new TLS session ticket is received.

通道:quic.session.version.negotiation#>

🌐 Channel: quic.session.version.negotiation

  • version <number> 为此会话配置的 QUIC 版本。
  • requestedVersions <number[]> 服务器宣传的版本。
  • supportedVersions <number[]> 本地支持的版本。
  • session quic.QuicSession

当客户端收到来自服务器的版本协商数据包时发布。会话总是在之后立即销毁。

🌐 Published when the client receives a Version Negotiation packet from the server. The session is always destroyed immediately after.

通道:quic.session.receive.origin#>

🌐 Channel: quic.session.receive.origin

  • origins <string[]> 服务器具有权威的来源列表。
  • session quic.QuicSession

当会话从对等方接收到 ORIGIN 帧(RFC 9412)时发布。

🌐 Published when the session receives an ORIGIN frame (RFC 9412) from the peer.

通道:quic.session.handshake#>

🌐 Channel: quic.session.handshake

在 TLS 握手完成时发布。

🌐 Published when the TLS handshake completes.

通道:quic.session.goaway#>

🌐 Channel: quic.session.goaway

  • session quic.QuicSession
  • lastStreamId <bigint> 对端可能已经处理的最高流 ID。

当对等方发送 HTTP/3 GOAWAY 帧时发布。ID 高于 lastStreamId 的流未被处理,可以在新连接上重试。lastStreamId-1n 表示没有流边界的关闭通知。

🌐 Published when the peer sends an HTTP/3 GOAWAY frame. Streams with IDs above lastStreamId were not processed and can be retried on a new connection. A lastStreamId of -1n indicates a shutdown notice without a stream boundary.

通道:quic.session.early.rejected#>

🌐 Channel: quic.session.early.rejected

  • session quic.QuicSession

当服务器拒绝 0-RTT 早期数据时发布。在 0-RTT 阶段打开的所有流都已被销毁。当预期 0-RTT 会成功时,这对于诊断延迟回归很有用。

🌐 Published when the server rejects 0-RTT early data. All streams that were opened during the 0-RTT phase have been destroyed. Useful for diagnosing latency regressions when 0-RTT is expected to succeed.

通道:quic.stream.closed#>

🌐 Channel: quic.stream.closed

  • stream quic.QuicStream
  • session quic.QuicSession
  • error <any> 导致关闭的错误,或者如果没有错误则为 undefined
  • stats quic.QuicStream.Stats 最终流统计。

当流被销毁时发布。stats 对象是销毁时最终统计信息的快照。

🌐 Published when a stream is destroyed. The stats object is a snapshot of the final statistics at the time of destruction.

通道:quic.stream.headers#>

🌐 Channel: quic.stream.headers

  • stream quic.QuicStream
  • session quic.QuicSession
  • headers <Object> 初始请求或响应头。

在流上收到初始头时发布。对于 HTTP/3 服务器端流,这包含请求伪头(:method:path 等)。对于客户端流,这包含响应头(:status 等)。

🌐 Published when initial headers are received on a stream. For HTTP/3 server-side streams, this contains request pseudo-headers (:method, :path, etc.). For client-side streams, this contains response headers (:status, etc.).

通道:quic.stream.trailers#>

🌐 Channel: quic.stream.trailers

  • stream quic.QuicStream
  • session quic.QuicSession
  • trailers <Object> 尾随头部。

在接收到流上的尾部头时发布。

🌐 Published when trailing headers are received on a stream.

通道:quic.stream.info#>

🌐 Channel: quic.stream.info

  • stream quic.QuicStream
  • session quic.QuicSession
  • headers <Object> 信息头。

当在流上收到信息性(1xx)头时发布(例如,103 早期提示)。

🌐 Published when informational (1xx) headers are received on a stream (e.g., 103 Early Hints).

通道:quic.stream.reset#>

🌐 Channel: quic.stream.reset

  • stream quic.QuicStream
  • session quic.QuicSession
  • error <any> 与重置相关的 QUIC 错误。

当流从对等方接收到 STOP_SENDING 或 RESET_STREAM 帧时发布,表示对等方已中止该流。这是诊断应用层问题(例如取消的请求)的一个关键信号。

🌐 Published when a stream receives a STOP_SENDING or RESET_STREAM frame from the peer, indicating the peer has aborted the stream. This is a key signal for diagnosing application-level issues such as cancelled requests.

通道:quic.stream.blocked#>

🌐 Channel: quic.stream.blocked

  • stream quic.QuicStream
  • session quic.QuicSession

当流被流量控制阻塞且无法发送数据时发布,直到对端增加流量控制窗口。对于诊断由流量控制引起的吞吐量问题很有用。

🌐 Published when a stream is flow-control blocked and cannot send data until the peer increases the flow control window. Useful for diagnosing throughput issues caused by flow control.

Node.js 中文网 - 粤ICP备13048890号