我正在使用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本身生成的缓冲区,因此是双重打包数据。为了避免任何混淆,我将其替换为通过读取图像获得的另一个缓冲区,这引发了同样的问题。
答案 0 :(得分: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>
来自This line of C++ code的 node-msgpack对此行为负责。拦截给予编码器的数据结构中的Buffer
实例时,它只是将其绑定转换为String
,相当于执行buffer.toString()
,默认情况下假定为UTF-8
编码,用上面的内容替换每个无法识别的字符。
下面建议的替代模块通过将缓冲区保留为原始字节而不是尝试将其转换为字符串来解决此问题,但这样做与其他MessagePack实现不兼容。如果兼容性是一个问题,那么解决这个问题的方法是使用UTF-8
,binary
或base64
之类的二进制安全编码提前编码非hex
缓冲区。 base64
或hex
将不可避免地增加数据的大小,但会使其保持一致,并且在通过HTTP传输数据时最安全。如果大小也是一个问题,那么通过像Snappy这样的流压缩算法来管理MessagePack结果可能是个不错的选择。
变成另一个模块msgpack-js(这是一个用javascript编写的msgpack编码器/解码器),保留原始二进制数据,从而解决了上述问题。他是这样做的:
我将格式扩展了一点,以便对undefined和Buffer实例进行编码和解码。
这需要三个以前标记为“保留”的新类型代码。此更改意味着使用这些新类型将使您的序列化数据与不具有相同扩展名的其他messagepack实现不兼容。
作为奖励,它的性能也比之前提到的基于C ++扩展的模块更高效。它也更年轻,所以可能没有经过彻底的测试。时间会证明。以下是基于one that was included in 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的性能仍然更高。