5

我正在使用node-msgpack对机器之间传递的消息进行编码和解码。我想做的一件事是将原始缓冲区数据包装在一个对象中并使用 Messagepack 对其进行编码。

msgpack = require('msgpack')
buf = <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 ...>
obj = {foo: buf}
packed = msgpack.pack(obj)

在上面的示例中,我想对嵌套在对象中的缓冲区的原始字节进行一致性检查。所以buf是这样获得的:

var buf = fs.readFileSync('some_image.png');

在一个完美的世界里,我会得到:

new Buffer(msgpack.unpack(packed).foo);

#> <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 ...>

相反,我最终得到了一些随机数。再深入一点,我最终会产生以下好奇心:

enc = 'ascii'
new Buffer(buf.toString(enc), enc)
#> <Buffer *ef bf bd* 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 ...>

buf
#> <Buffer *89* 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 02 00 ...>

第一个字节是问题所在。我尝试使用不同的编码但没有运气。这里发生了什么,我能做些什么来规避这个问题?

编辑:

最初,这buf是我使用 msgpack 本身生成的缓冲区,因此对数据进行了双重打包。为避免混淆,我将其替换为通过读取图像获得的另一个缓冲区,这引发了同样的问题。

4

1 回答 1

5

base64当使用除和之外的任何编码文本解码二进制数据时,会出现缓冲区损坏问题hex。似乎没有被node-msgpack 拾取。它似乎会自动尝试使用“utf-8”,这会不可逆转地破坏缓冲区。他们必须做类似的事情,所以我们最终不会得到一堆缓冲区对象而不是普通字符串,这主要是我们的 msgpack 对象通常由什么组成的。


编辑

上面显示的有问题的三个字节代表 UTF-8 Replacement Character。快速测试表明,这个字符是用来替换0x89开头无法识别的字节:

new Buffer((new Buffer('89', 'hex')).toString('utf-8'), 'utf-8')
//> <Buffer ef bf bd>

这行来自node-msgpack的 C++ 代码负责此行为。当截取Buffer给编码器的数据结构中的实例时,它只是将其绑定转换为 a String,相当于执行buffer.toString()默认假设UTF-8编码,用上面的替换每个无法识别的字符。

下面建议的替代模块通过将缓冲区保留为原始字节来解决此问题,而不是尝试将其转换为字符串,但这样做与其他 MessagePack 实现不兼容。如果兼容性是一个问题,解决这个问题的方法是UTF-8使用二进制安全编码提前对非缓冲区进行编码,如binary,base64hex. base64或者hex将不可避免地显着增加数据的大小,但会保持一致并且在通过 HTTP 传输数据时使用起来最安全。如果大小也是一个问题,那么通过像Snappy这样的流压缩算法传送 MessagePack 结果可能是一个不错的选择。


结果是另一个模块msgpack-js(它是一个用 javascript 编写的 msgpack 编码器/解码器),保留原始二进制数据,从而解决了上述问题。他是这样做的:

我稍微扩展了格式以允许对未定义和 Buffer 实例进行编码和解码。

这需要三个以前标记为“保留”的新类型代码。此更改意味着使用这些新类型将使您的序列化数据与其他没有相同扩展名的消息包实现不兼容。

作为奖励,它也比前面提到的基于 C++ 扩展的模块性能更高。它也更年轻,所以可能没有经过彻底的测试。时间会证明一切。这是我做的快速基准测试的结果,基于node-msgpack 中包含的基准,比较了两个库(以及本机 JSON 解析器):

node-msgpack pack:   3793 ms
node-msgpack unpack: 1340 ms

msgpack-js pack:   3132 ms
msgpack-js unpack: 983 ms

json pack:   1223 ms
json unpack: 483 ms

因此,虽然我们看到原生 javascript msgpack 解码器的性能有所提高,但 JSON 的性能仍然更高。

于 2012-12-22T01:46:28.250 回答