摘要

  • STOP_SENDING 表示接收方不再需要某个进入方向的数据,但不证明此前的字节未被忽略或消费。
  • RESET_STREAM 只终止对端的发送方向;final size 记录消耗的流控额度,不记录完成或撤销的工作。
  • 传输事实必须与应用接纳、取消确认、持久化影响、补偿以及最终业务结果分开记录。

客户端超时后可能不再需要响应,于是发送带有应用错误码的 STOP_SENDING。这是明确的 QUIC 传输事件:它请求对端停止在某一条流的一个方向上发送数据。但它不是远端订单、任务或请求已经取消的证明。数据在网络中的状态,与业务操作在应用中的状态,不是同一条状态机。

RFC 9000 允许已经不关心某条流上接收数据的应用中止读取。当接收部分处于 Recv 或 Size Known 时,传输层应发送 STOP_SENDING,以促使对向方向关闭。规范同时明确指出,这并不保证传入数据会被忽略。此前的 STREAM 字节可能已经到达、交给应用,甚至已经产生应用行为。发送 STOP_SENDING 后仍收到的 STREAM 字节,即使被传输层丢弃,也仍计入流和连接的流控额度。

对端的回应是独立的状态转换。如果对端的发送部分处于 Ready 或 Send,它必须发送 RESET_STREAM。处于 Data Sent 时,可以等待未完成数据被确认或被判定为丢失;若数据被判定为丢失,应发送 RESET_STREAM 而不是重新发送这些数据。对端应复制 STOP_SENDING 中的应用错误码,但也可以选择不同的错误码。因此,STOP_SENDING 携带的码与之后观察到的 RESET_STREAM 错误码必须分开保存。

方向性是最容易被忽略的边界。RESET_STREAM 突然终止的只是发送部分。双向流的另一方向仍然独立运行。若要推动两个方向都结束,一个端点可以用 RESET_STREAM 终止自己的发送方向,再用 STOP_SENDING 促使对向方向停止。两者都不会关闭连接,也不能证明整个请求对或业务流程已经取消。

final size 属于流控证据。它表示该流消耗的连接级流控额度。一旦已知就不能改变,无论流是正常结束还是被重置。它不表示应用完成了多少工作,也不表示远端是否接纳操作、是否撤销影响。发送 RESET_STREAM 后,端点停止在该方向发送和重传 STREAM 帧;这说明传输行为结束,不说明远端应用状态被恢复。

可靠性在这里也有明确范围。QUIC 不会把丢失的整个数据包原样重传,而是需要时在新帧中再次发送相关信息。RESET_STREAM 会持续发送到获得确认,或直到该流的全部数据得到确认。STOP_SENDING 会持续发送到接收部分进入 Data Recvd 或 Reset Recvd。接收或确认只证明 QUIC 流状态机取得进展,不能证明对端没有消费此前字节、没有取消工作、没有回滚影响,或补偿已经成功。

证据账本应记录连接身份、stream ID、发起方、单向或双向类型及受影响方向,并分别记录停止读取的本地决定、STOP_SENDING 的发送和重传、每个应用错误码、RESET_STREAM 的接收及其独立错误码、final size、流控计算以及后续 STREAM 字节。远端接纳或消费、取消接受或拒绝、持久化影响、回滚、补偿和最终结果,都需要额外的应用证据。

这也解释了它与相邻议题的区别。TR-045 关注 ACK 和数据包处理;TR-046 关注流控额度这一权限;TR-052 关注 DATAGRAM 的消息边界及其不提供的交付保证;TR-053 关注 CONNECTION_CLOSE 和整体传输状态结束。STOP_SENDING 不属于这些类别:它是在连接仍可能存活时,请求停止一条流的一个方向。