规范说:
新建立的流的标识符必须是数字上的 大于发起终端节点已打开的所有流,或 保留。这控制使用 HEADERS 帧打开的流 以及使用 PUSH_PROMISE 保留的流。一个终结点 收到意外的流标识符必须响应 类型为 PROTOCOL_ERROR 的连接错误(第 5.4.1 节)。
对于发送PUSH_PROMISE
的服务器的情况,对我来说,符合要求的服务器必须发送严格递增的流 ID 是有意义的。但我不明白客户应该如何检测这种情况。
例如,在一个连接上,如果服务器发送:
PUSH_PROMISE
承诺流2PUSH_PROMISE
承诺流 4
由于客户端可能收到的并发性
PUSH_PROMISE
承诺流 4PUSH_PROMISE
承诺流 2
规范会让我认为客户端应该在这方面出错,但服务器没有做错任何事。
我在这里错过了什么?
如果服务器先写PUSH_PROMISE[stream=2]
然后PUSH_PROMISE[stream=4]
,那么这些帧将以相同的顺序传送(这是由TCP保证的)。
客户端的任务是以有序的方式从套接字读取。 对于HTTP/2实现,要求更加严格,因为它不仅必须以有序的方式从套接字读取,而且还必须以有序的方式解析帧。
这是必需的,因为PUSH_PROMISE
帧携带 HPACK 块,并且为了使服务器和客户端 HPACK 上下文保持同步,必须按顺序处理帧(或至少这些帧的 HPACK 块),因此stream=2
在stream=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
由于读取和解析是顺序的,并且没有其他线程从同一套接字读取,因此满足排序保证。