为什么重新排序gzip数据包会损坏输出?

时间:2013-10-30 00:19:42

标签: c networking gzip zlib gzipstream

我正在使用zlib中发布的gzip代码的想法。 对于初始化,我使用deflateInit2(p_strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY)。 我正在拉一条小溪。每个包含Z_FULL_FLUSH的数据包,除了我使用Z_FINISH的最后一个数据包。 在压缩每个数据包之后,我正在重新排序数据包。

数据包中的数据---> [zip] ---> [重新排序] ---> ...

如果我在zip之后给数据充气,我会在压缩之前得到确切的文件。 如果我在重新排序数据包之后膨胀数据(再次:每个数据包用Z_FULL_FLUSH缩小,除了最后一个Z_FINISH)我得到一个与压缩之前的原始文件非常相似的文件。区别在于文件的末尾:缺少字节。那是因为当我给它充气时,我收到最后一个数据包的错误(Z_DATA_ERROR)。如果我膨胀,比方说,使用50KB的块,重新排序后的膨胀文件与输入的文件相同,少于< 50KB(整个最后一个数据包因错误而消失)。如果我将膨胀块大小减少到8B,我仍然得到Z_DATA_ERROR,但现在我在膨胀时丢失了更少的数据,(在我的例子中,我从原始文件中缺少一个字节)。

我没有重新排序最后一个数据包(Z_FINISH)。 我尝试使用Z_FULL_FLUSH发送所有数据包,然后发送另一个“空”数据包(仅Z_FINISH,即10个字节)。

为什么会这样? 如果我使用Z_FULL_FLUSH,为什么inflater不能正确充气呢? 它记得收缩包的顺序吗?

任何信息都会有所帮助, 感谢。

2 个答案:

答案 0 :(得分:3)

由于您正在使用Z_FULL_FLUSH删除每次刷新时的历史记录,因此您可以对数据包重新排序,除了最后一个。您在上执行的Z_FINISH必须是最后一个数据包。但它不需要任何数据。您可以使用Z_FULL_FLUSH从上一个数据包中提取所有数据,然后执行一个没有输入数据和Z_FINISH的最终数据包。这将允许您在空的那个之前重新排序数据包。最后总是最后一个。

原因是deflate格式是自终止的,因此最后一个标记标记了流的结尾。如果你把它重新排序到某个地方的中间位置,那么当它撞到那个数据包时就会停止通货膨胀。

需要在开头和结尾维护gzip头和尾部,并相应地更新预告片中的CRC。最后的CRC校验取决于数据的顺序。

为什么要尝试做你想做的事情?你在优化什么?

答案 1 :(得分:1)

GZip是一种流媒体协议。压缩取决于流的先前历史。你不能重新排序。