http2:PUSH_PROMISE保留的流 ID 验证



规范说:

新建立的流的标识符必须是数字上的 大于发起终端节点已打开的所有流,或 保留。这控制使用 HEADERS 帧打开的流 以及使用 PUSH_PROMISE 保留的流。一个终结点 收到意外的流标识符必须响应 类型为 PROTOCOL_ERROR 的连接错误(第 5.4.1 节)。

对于发送PUSH_PROMISE的服务器的情况,对我来说,符合要求的服务器必须发送严格递增的流 ID 是有意义的。但我不明白客户应该如何检测这种情况。

例如,在一个连接上,如果服务器发送:

  1. PUSH_PROMISE承诺流2
  2. PUSH_PROMISE承诺流 4

由于客户端可能收到的并发性

  1. PUSH_PROMISE承诺流 4
  2. PUSH_PROMISE承诺流 2

规范会让我认为客户端应该在这方面出错,但服务器没有做错任何事。

我在这里错过了什么?

如果服务器先写PUSH_PROMISE[stream=2]然后PUSH_PROMISE[stream=4],那么这些帧将以相同的顺序传送(这是由TCP保证的)。

客户端的任务是以有序的方式从套接字读取。 对于HTTP/2实现,要求更加严格,因为它不仅必须以有序的方式从套接字读取,而且还必须以有序的方式解析帧。

这是必需的,因为PUSH_PROMISE

帧携带 HPACK 块,并且为了使服务器和客户端 HPACK 上下文保持同步,必须按顺序处理帧(或至少这些帧的 HPACK 块),因此stream=2stream=4之前

。之后,客户端可以自由地同时处理 2 帧。

对于实现,这实际上很容易实现,因为分配给执行 I/O 读取的线程通常执行以下操作:

loop
read bytes from socket
if no bytes or socket closed -> break loop
parse read bytes (with HPACK decoding) -> produce frame objects
pass frame objects to upper software layer
end loop

由于读取和解析是顺序的,并且没有其他线程从同一套接字读取,因此满足排序保证。

最新更新