hpack编码整数意义
hpack encoding integer significance
读完后,https://httpwg.org/specs/rfc7541.html#integer.representation
我对很多事情感到困惑,尽管我似乎掌握了这个想法的总体要点。
其一,'prefixes' exactly/what 的目的是什么?
两人:
C.1.1. Example 1: Encoding 10 Using a 5-Bit Prefix
The value 10 is to be encoded with a 5-bit prefix.
10 is less than 31 (2^5 - 1) and is represented using the 5-bit prefix.
0 1 2 3 4 5 6 7
+---+---+---+---+---+---+---+---+
| X | X | X | 0 | 1 | 0 | 1 | 0 | 10 stored on 5 bits
+---+---+---+---+---+---+---+---+
前导 X 是什么?起始0是什么?
>>> bin(10)
'0b1010'
>>>
在 python IDE 中键入此内容,您会看到几乎相同的输出...为什么不同?
这是当数字适合前缀位数时,看起来很简单。
C.1.2. Example 2: Encoding 1337 Using a 5-Bit Prefix
The value I=1337 is to be encoded with a 5-bit prefix.
1337 is greater than 31 (25 - 1).
The 5-bit prefix is filled with its max value (31).
I = 1337 - (25 - 1) = 1306.
I (1306) is greater than or equal to 128, so the while loop body executes:
I % 128 == 26
26 + 128 == 154
154 is encoded in 8 bits as: 10011010
I is set to 10 (1306 / 128 == 10)
I is no longer greater than or equal to 128, so the while loop terminates.
I, now 10, is encoded in 8 bits as: 00001010.
The process ends.
0 1 2 3 4 5 6 7
+---+---+---+---+---+---+---+---+
| X | X | X | 1 | 1 | 1 | 1 | 1 | Prefix = 31, I = 1306
| 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1306>=128, encode(154), I=1306/128
| 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 10<128, encode(10), done
+---+---+---+---+---+---+---+---+
类似八位位组的图表显示正在生成三个不同的数字...由于数字是在整个循环中生成的,您如何在整数中复制这个类似八位组的图表?实际最终结果如何?图表或“I”为 10,或 00001010。
def f(a, b):
if a < 2**b - 1:
print(a)
else:
c = 2**b - 1
remain = a - c
print(c)
if remain >= 128:
while 1:
e = remain % 128
g = e + 128
remain = remain / 128
if remain >= 128:
continue
else:
print(remain)
c+=int(remain)
print(c)
break
当我试图解决这个问题时,我写了一个快速的 python 实现,看来我还剩下一些 useless
个变量,其中一个是 g
在文档中是 26 + 128 == 154.
最后,128从何而来?除了 2 的 7 次方是 128 之外,我找不到数字之间的任何关系,但为什么这很重要?这是因为第一位被保留为继续标志吗?一个八位字节包含 8 位,所以 8 - 1 = 7?
For one, What are the 'prefixes' exactly/what is their purpose?
整数在 HPACK 消息中的几个地方使用,并且它们通常具有不能用于实际整数的前导位。因此,通常会有一些前导数字无法用于整数本身。它们由 X 表示。出于此计算的目的,它不会说明这些 X 是什么:可能是 000、111、010 或...等等。此外,不会总是有 3 个 X - 这只是一个例子。只能有一个前导 X,或两个,或四个...等等
例如,要查找先前解码的 HPACK header,我们使用 6.1. Indexed Header Field Representation,它以前导 1 开头,后跟 table 索引值。因此,1 就是前面示例中的 X。我们有 7 位(而不是您问题中原始示例中的 5 位)。如果 table 索引值为 127 或更小,我们可以使用这 7 位来表示它。如果它 >= 127 那么我们需要做一些额外的工作(我们会回到这个)。
如果它是我们想要添加到 table 的新值(以便在未来的请求中重用),但是我们已经在 table 中有了那个 header 名称(所以它是只是我们想要作为新条目的那个名称的新值)然后我们使用 6.2.1. Literal Header Field with Incremental Indexing。这在开头有 2 位(01
- 这是 X),这次我们只有 6 位来表示我们要重用的名称的索引。所以在这种情况下有两个 X。
所以不要担心有 3 个 X - 这只是一个例子。在上面的示例中,分别有一个 X(因为第一位必须是 1)和两个 X(因为前两位必须是 01)。 Integer Representation section 告诉你如何处理任何带前缀的整数,无论是前缀为 1、2、3 ......等等不可用的“X”位。
What are the leading Xs? What is the starting 0 for?
上面讨论了前导 X。开头的 0 只是因为,在这个例子中我们有 5 位来表示整数,只需要 4 位。所以我们用 0 填充它。如果要编码的值是 20,它将是 10100
。如果值为 40,我们无法将其放入 5 位中,因此需要做其他事情。
Typing this in the python IDE, you see almost the same output... Why does it differ?
Python 使用 0b
来显示它是一个二进制数。它不会显示任何前导零。所以 0b1010
与 0b01010
相同,也与 0b00001010
.
相同
This is when the number fits within the number of prefix bits though, making it seemingly simple.
没错。如果您需要的位数超过您拥有的位数,则没有 space。您不能只使用更多位,因为 HPACK 不知道您是否打算使用更多位(因此应该查看下一个字节)或者它是否只是一个直接数字(因此只查看这个字节)。它需要一个信号来知道这一点。该信号使用全 1。
所以要用5位编码40,我们需要用11111
表示“不够大”,溢出到下一个字节。 11111
在二进制中是 31,所以我们知道它比那个大,所以我们不会浪费它,而是使用它,并从 40 中减去它,留下 9 以在下一个字节中编码。一个新的附加字节为我们提供了 8 个新位(我们很快就会发现实际上只有 7 个,因为第一位用于表示进一步溢出)。这足够了,所以我们可以使用 00001001
来编码我们的 9。所以我们的复数用两个字节表示:XXX11111
和 00001001
.
如果我们想要编码的值大于第一个前缀位所能固定的值,并且剩余的值大于 127 可以放入第二个字节的可用 7 位,那么我们不能使用这个使用两个字节的溢出机制。相反,我们使用另一种使用三个字节的“溢出,溢出”机制:
对于这种“溢出,溢出”机制,我们像往常一样将第一个字节的位设置为 1s 以进行溢出(XXX11111
),然后将第二个字节的第一个位设置为 1。这剩下 7可用于对值进行编码的位,加上我们将不得不使用的第三个字节中的下一个 8 位(实际上只有第三个字节的 7 位,因为它再次使用第一个位来指示另一个溢出)。
他们可以通过多种方式使用第二个和第三个字节来解决这个问题。他们决定做的是将其编码为两个数字:128 mod 和 128 乘数。
1337 = 31 + (128 * 10) + 26
所以这意味着第一个字节按照前面的例子设置为 31,第二个字节设置为 26(即 11010
)加上前导 1 以表明我们正在使用溢出溢出方法(所以100011010
),第三个字节设置为10(或00001010
)。
所以 1337 被编码为三个字节:XXX11111 100011010 00001010
(包括将 X 设置为那些值)。
使用 128 mod 和乘法器非常有效,这意味着这个大数(实际上是最大 16,383 的任何数)可以用三个字节表示,这并非巧合,也是可以表示的最大整数以 7 + 7 = 14 位表示)。但这确实需要一点头脑!
如果它大于 16,383,那么我们需要以类似的方式进行另一轮溢出。
所有这些看起来非常复杂,但实际上编码起来相对简单、高效。计算机可以很容易和快速地做到这一点y.
It seems that i am left with a few useless variables, one being g
您没有在 if
语句中打印此值。只有 else
中剩余的值。您需要将两者都打印出来。
which in the documentation is the 26 + 128 == 154.
Lastly, where does 128 come from? I can't find any relation between the numbers besides the fact 2 raised to the 7th power is 128, but why is that significant? Is this because the first bit is reserved as a continuation flag? and an octet contains 8 bits so 8 - 1 = 7?
没错,这是因为第一位(值 128)需要按照上面的解释设置,以表明我们 continuing/overflowing 需要第三个字节。
读完后,https://httpwg.org/specs/rfc7541.html#integer.representation
我对很多事情感到困惑,尽管我似乎掌握了这个想法的总体要点。
其一,'prefixes' exactly/what 的目的是什么?
两人:
C.1.1. Example 1: Encoding 10 Using a 5-Bit Prefix
The value 10 is to be encoded with a 5-bit prefix.
10 is less than 31 (2^5 - 1) and is represented using the 5-bit prefix.
0 1 2 3 4 5 6 7
+---+---+---+---+---+---+---+---+
| X | X | X | 0 | 1 | 0 | 1 | 0 | 10 stored on 5 bits
+---+---+---+---+---+---+---+---+
前导 X 是什么?起始0是什么?
>>> bin(10)
'0b1010'
>>>
在 python IDE 中键入此内容,您会看到几乎相同的输出...为什么不同? 这是当数字适合前缀位数时,看起来很简单。
C.1.2. Example 2: Encoding 1337 Using a 5-Bit Prefix
The value I=1337 is to be encoded with a 5-bit prefix.
1337 is greater than 31 (25 - 1).
The 5-bit prefix is filled with its max value (31).
I = 1337 - (25 - 1) = 1306.
I (1306) is greater than or equal to 128, so the while loop body executes:
I % 128 == 26
26 + 128 == 154
154 is encoded in 8 bits as: 10011010
I is set to 10 (1306 / 128 == 10)
I is no longer greater than or equal to 128, so the while loop terminates.
I, now 10, is encoded in 8 bits as: 00001010.
The process ends.
0 1 2 3 4 5 6 7
+---+---+---+---+---+---+---+---+
| X | X | X | 1 | 1 | 1 | 1 | 1 | Prefix = 31, I = 1306
| 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1306>=128, encode(154), I=1306/128
| 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 10<128, encode(10), done
+---+---+---+---+---+---+---+---+
类似八位位组的图表显示正在生成三个不同的数字...由于数字是在整个循环中生成的,您如何在整数中复制这个类似八位组的图表?实际最终结果如何?图表或“I”为 10,或 00001010。
def f(a, b):
if a < 2**b - 1:
print(a)
else:
c = 2**b - 1
remain = a - c
print(c)
if remain >= 128:
while 1:
e = remain % 128
g = e + 128
remain = remain / 128
if remain >= 128:
continue
else:
print(remain)
c+=int(remain)
print(c)
break
当我试图解决这个问题时,我写了一个快速的 python 实现,看来我还剩下一些 useless
个变量,其中一个是 g
在文档中是 26 + 128 == 154.
最后,128从何而来?除了 2 的 7 次方是 128 之外,我找不到数字之间的任何关系,但为什么这很重要?这是因为第一位被保留为继续标志吗?一个八位字节包含 8 位,所以 8 - 1 = 7?
For one, What are the 'prefixes' exactly/what is their purpose?
整数在 HPACK 消息中的几个地方使用,并且它们通常具有不能用于实际整数的前导位。因此,通常会有一些前导数字无法用于整数本身。它们由 X 表示。出于此计算的目的,它不会说明这些 X 是什么:可能是 000、111、010 或...等等。此外,不会总是有 3 个 X - 这只是一个例子。只能有一个前导 X,或两个,或四个...等等
例如,要查找先前解码的 HPACK header,我们使用 6.1. Indexed Header Field Representation,它以前导 1 开头,后跟 table 索引值。因此,1 就是前面示例中的 X。我们有 7 位(而不是您问题中原始示例中的 5 位)。如果 table 索引值为 127 或更小,我们可以使用这 7 位来表示它。如果它 >= 127 那么我们需要做一些额外的工作(我们会回到这个)。
如果它是我们想要添加到 table 的新值(以便在未来的请求中重用),但是我们已经在 table 中有了那个 header 名称(所以它是只是我们想要作为新条目的那个名称的新值)然后我们使用 6.2.1. Literal Header Field with Incremental Indexing。这在开头有 2 位(01
- 这是 X),这次我们只有 6 位来表示我们要重用的名称的索引。所以在这种情况下有两个 X。
所以不要担心有 3 个 X - 这只是一个例子。在上面的示例中,分别有一个 X(因为第一位必须是 1)和两个 X(因为前两位必须是 01)。 Integer Representation section 告诉你如何处理任何带前缀的整数,无论是前缀为 1、2、3 ......等等不可用的“X”位。
What are the leading Xs? What is the starting 0 for?
上面讨论了前导 X。开头的 0 只是因为,在这个例子中我们有 5 位来表示整数,只需要 4 位。所以我们用 0 填充它。如果要编码的值是 20,它将是 10100
。如果值为 40,我们无法将其放入 5 位中,因此需要做其他事情。
Typing this in the python IDE, you see almost the same output... Why does it differ?
Python 使用 0b
来显示它是一个二进制数。它不会显示任何前导零。所以 0b1010
与 0b01010
相同,也与 0b00001010
.
This is when the number fits within the number of prefix bits though, making it seemingly simple.
没错。如果您需要的位数超过您拥有的位数,则没有 space。您不能只使用更多位,因为 HPACK 不知道您是否打算使用更多位(因此应该查看下一个字节)或者它是否只是一个直接数字(因此只查看这个字节)。它需要一个信号来知道这一点。该信号使用全 1。
所以要用5位编码40,我们需要用11111
表示“不够大”,溢出到下一个字节。 11111
在二进制中是 31,所以我们知道它比那个大,所以我们不会浪费它,而是使用它,并从 40 中减去它,留下 9 以在下一个字节中编码。一个新的附加字节为我们提供了 8 个新位(我们很快就会发现实际上只有 7 个,因为第一位用于表示进一步溢出)。这足够了,所以我们可以使用 00001001
来编码我们的 9。所以我们的复数用两个字节表示:XXX11111
和 00001001
.
如果我们想要编码的值大于第一个前缀位所能固定的值,并且剩余的值大于 127 可以放入第二个字节的可用 7 位,那么我们不能使用这个使用两个字节的溢出机制。相反,我们使用另一种使用三个字节的“溢出,溢出”机制:
对于这种“溢出,溢出”机制,我们像往常一样将第一个字节的位设置为 1s 以进行溢出(XXX11111
),然后将第二个字节的第一个位设置为 1。这剩下 7可用于对值进行编码的位,加上我们将不得不使用的第三个字节中的下一个 8 位(实际上只有第三个字节的 7 位,因为它再次使用第一个位来指示另一个溢出)。
他们可以通过多种方式使用第二个和第三个字节来解决这个问题。他们决定做的是将其编码为两个数字:128 mod 和 128 乘数。
1337 = 31 + (128 * 10) + 26
所以这意味着第一个字节按照前面的例子设置为 31,第二个字节设置为 26(即 11010
)加上前导 1 以表明我们正在使用溢出溢出方法(所以100011010
),第三个字节设置为10(或00001010
)。
所以 1337 被编码为三个字节:XXX11111 100011010 00001010
(包括将 X 设置为那些值)。
使用 128 mod 和乘法器非常有效,这意味着这个大数(实际上是最大 16,383 的任何数)可以用三个字节表示,这并非巧合,也是可以表示的最大整数以 7 + 7 = 14 位表示)。但这确实需要一点头脑!
如果它大于 16,383,那么我们需要以类似的方式进行另一轮溢出。
所有这些看起来非常复杂,但实际上编码起来相对简单、高效。计算机可以很容易和快速地做到这一点y.
It seems that i am left with a few useless variables, one being g
您没有在 if
语句中打印此值。只有 else
中剩余的值。您需要将两者都打印出来。
which in the documentation is the 26 + 128 == 154. Lastly, where does 128 come from? I can't find any relation between the numbers besides the fact 2 raised to the 7th power is 128, but why is that significant? Is this because the first bit is reserved as a continuation flag? and an octet contains 8 bits so 8 - 1 = 7?
没错,这是因为第一位(值 128)需要按照上面的解释设置,以表明我们 continuing/overflowing 需要第三个字节。