0

规范说:

新建立的流的标识符在数值上必须大于发起端点已打开或保留的所有流。这管理使用 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

规范会让我认为客户端应该对此出错,但服务器没有做错任何事情。

我在这里想念什么?

4

1 回答 1

3

如果服务器写入PUSH_PROMISE[stream=2]then 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

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

于 2018-01-12T07:50:50.603 回答