gzdecode()和inflate_add()之间的二进制互操作性

时间:2016-12-25 15:29:20

标签: php websocket zlib php-7 deflate

我不久前写了一个小的WebSocket库,发现添加gzip支持非常简单。我当时并没有完全意识到 componentWillMount() / deflate_init() / deflate_add() / inflate_init()函数实际上只是PHP 7,而现在我只是#7;我希望能够在PHP 5环境下运行我的WebSocket服务器。

我的问题是,inflate_add()产生的输出与deflate_add()略有不同 - 在下面的测试用例中只有一个字符。

基于gzdeflate() / deflate_add()的方法在浏览器中完美运行,因此inflate_add()的输出不正确。我猜gzdeflate() / gzdeflate()正在使用zlib和不同的底层选项 - 可能与流状态有关吗? - 这导致一切都崩溃了。

最终我想知道我是否可以说服PHP 5-era zlib函数输出"更正"泄密的数据。

首先,我在PHP 7上使用基于gzinflate() / deflate_init()的方法:

deflate_add()

如果我使用$data = "ABC"; $ctx = deflate_init(ZLIB_ENCODING_RAW); // unfortunately I can't find the gigantic blog post with example code // that I learned from :(, but it contained the Ruby equivalent of the // the substr() below. I blinked at it a bit but apparently this is how // it's done. $deflated = substr(deflate_add($ctx, $data, ZLIB_SYNC_FLUSH), 0, -4); // $deflated is now "rtr\6\0" $ictx = inflate_init(ZLIB_ENCODING_RAW); $data2 = inflate_add($ictx, $deflated, ZLIB_NO_FLUSH); // $data2 is now "ABC" / gzdeflate()会发生什么:

gzinflate()

尝试$data = "ABC"; $deflated = gzdeflate($data, 9, ZLIB_ENCODING_RAW); // $deflated is now "str\6\0" $output = gzinflate($deflated); // $output is now "ABC" gzinflate()的输出会产生 inflate_add() 。作为TL; DR:

data error

1 个答案:

答案 0 :(得分:0)

你所说的正确是不正确的,你所说的不正确是正确的。

使用deflate_add,您故意创建一个未终止的,即无效的deflate流。为什么,我不知道。 (显然,你也不是,因为这来自一个你无法找到的“巨大的博客文章”。)这是用ZLIB_SYNC_FLUSH完成当前的deflate块并添加一个空的存储块。 substr(,,-4)正在删除末尾的大部分空存储块,留下一个不完整的无效膨胀流,过早地在存储块的中间结束。

另一方面,

gzdeflate正在创建一个正确终止的deflate流,其中一个deflate块被标记为最后一个块。两个流之间的唯一区别是第一个(最低有效)位,它是1以标记最后一个块。

你没有说正确终止的deflate流是如何“导致一切崩溃”。在任何情况下,您都可以使用deflate_add而不是ZLIB_FINISH使用ZLIB_SYNC_FLUSH制作正确终止的deflate流,并放弃substr

如果这就是您所要求的,则无法使用gzdeflate制作无效的deflate流。你不能只改变第一位,因为对于一个更大的字符串,最后一个块可能不是第一个块。