You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HTTP/3 QUIC发送RESET_STREAM帧时Final Size字段设置咨询

QUIC流重置帧Final Size取值与相关实现问题解答

问题场景

  • 流发送方已连续发送总计10000字节的流数据
  • 接收方返回ACK确认已收到0-8000字节范围的数据,发送方已收到该确认
  • 发送方此时需要发送RESET_STREAM(流重置)帧,需确认帧中final size(最终大小)字段的正确取值,候选值为10000、8000

规范判定结论

Final Size正确取值

根据RFC 9000第4.5节对Stream Final Size的定义:

流的最终大小为该流消耗的流量控制额度。若流上所有连续字节均被发送一次,最终大小即为已发送的字节总数;通用规则为,最终大小是流上已发送的最大偏移字节的偏移值加1,未发送任何字节时取值为0。

本场景中发送方已经发出的流数据总长度为10000字节,对应最大字节偏移为9999(偏移从0开始计数),因此Final Size的正确取值为10000,对应选项a。接收方的ACK确认进度不影响该字段的取值,Final Size是发送方侧对流发送总长度的权威声明,和对端实际接收进度无关。

发送RESET_STREAM后的流发送规则

咨询者提出的“发送RESET_STREAM帧后不得再在对应流上进行任何STREAM帧的新发与重传”的理解完全正确。根据RFC 9000第19.4节的强制规定:

端点发送RESET_STREAM帧后,需停止对应流上STREAM帧的发送与重传;RESET_STREAM的接收方可丢弃该流上已收到的所有数据。

Nginx QUIC实现的对应缺陷

目前Nginx的QUIC实现存在不符合上述规范的逻辑问题:发送RESET_STREAM帧后仍可能触发旧STREAM帧的重传。
问题根因在于:Nginx HTTP/3实现将所有待发送帧写入ctx->frames队列后,对应的qs流对象会被提前删除。重传逻辑遍历到待重传的STREAM帧时,无法通过流ID找到对应的流对象,原本用于拦截重置流帧重传的状态判断分支失效。
相关问题代码片段如下:

void
ngx_quic_resend_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
{
case NGX_QUIC_FT_STREAM:
    qs = ngx_quic_find_stream(&qc->streams.tree, f->u.stream.stream_id);

    if (qs) {
        if (qs->send_state == NGX_QUIC_STREAM_SEND_RESET_SENT
            || qs->send_state == NGX_QUIC_STREAM_SEND_RESET_RECVD)
        {
            ngx_quic_free_frame(c, f);
            break;
        }
    }
}

上述代码仅在能查到流对象qs时,才会判断流是否已进入重置状态、释放待重传的STREAM帧;如果流对象已被删除,判断逻辑直接跳过,待重传的STREAM帧会被正常发出,违反RFC规范要求。


内容的提问来源于stack exchange,提问作者mingkun bian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 17:21:26