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 来显示它是一个二进制数。它不会显示任何前导零。所以 0b10100b01010 相同,也与 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。所以我们的复数用两个字节表示:XXX1111100001001.

如果我们想要编码的值大于第一个前缀位所能固定的值,并且剩余的值大于 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 需要第三个字节。