http2: PUSH_PROMISE 保留流 ID 验证
http2: PUSH_PROMISE reserved stream id validation
The spec 说:
The identifier of a newly established stream MUST be numerically
greater than all streams that the initiating endpoint has opened or
reserved. This governs streams that are opened using a HEADERS frame
and streams that are reserved using PUSH_PROMISE. An endpoint that
receives an unexpected stream identifier MUST respond with a
connection error (Section 5.4.1) of type PROTOCOL_ERROR.
对于发送 PUSH_PROMISE
的服务器,符合要求的服务器必须发送严格递增的流 ID,这对我来说很有意义。但我不明白客户应该如何检测这种情况。
例如,在一个连接上,如果服务器发送:
PUSH_PROMISE
承诺流 2
PUSH_PROMISE
承诺流 4
由于并发性,客户端可能会收到
PUSH_PROMISE
承诺流 4
PUSH_PROMISE
承诺流 2
规范让我认为客户端应该在这方面出错,但服务器没有做错。
我在这里错过了什么?
如果服务器写入 PUSH_PROMISE[stream=2]
然后 PUSH_PROMISE[stream=4]
,那么这些帧将以相同的顺序传送(这是由 TCP 保证的)。
客户端的任务是按顺序从套接字中读取。
对于 HTTP/2 实现,要求甚至更严格,因为它不仅必须以有序的方式从套接字读取,而且还必须以有序的方式解析帧。
这是 PUSH_PROMISE
帧携带 HPACK 块这一事实所必需的,为了保持服务器和客户端 HPACK 上下文同步,帧(或至少这些帧的 HPACK 块)必须顺序处理,所以stream=2
before 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
由于读取和解析是顺序的并且没有其他线程从同一个套接字读取,因此满足顺序保证。
The spec 说:
The identifier of a newly established stream MUST be numerically greater than all streams that the initiating endpoint has opened or reserved. This governs streams that are opened using a HEADERS frame and streams that are reserved using PUSH_PROMISE. An endpoint that receives an unexpected stream identifier MUST respond with a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
对于发送 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
before 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
由于读取和解析是顺序的并且没有其他线程从同一个套接字读取,因此满足顺序保证。