zlib inflate()和网络链接

时间:2016-08-26 17:17:22

标签: c++ zlib

我有2个通过网络链接进行通信的应用程序。发件人将使用zlib的deflate()压缩数据包并通过网络发送。接收器然后将使用inflate()解压缩数据。数据包可能会通过网络链路丢失;为了减少减压错误,我实施了以下方法:
发件人

  1. 大部分时间用Z_SYNC_FLUSH调用deflate(),但是用Z_FULL_FLUSH间歇性地调用deflate()。

  2. 发送(连同数据)一个2字节的字段,其中包含一个指示是否使用了FULL_FLUSH或SYNC_FLUSH的位和序列号。

  3. 接收方

    1. 读入数据;并使用序列号,检测是否 数据包已丢失。当没有数据包丢失时,2字节是 删除,解压缩工作正常。
    2. 当检测到丢包时,接收方检查是否丢失 当前数据包是FULL_FLUSH或SYNC_FLUSH数据包。

      • 如果它是一个SYNC_FLUSH,那么只需丢弃数据包,然后继续下一个数据包。

      • 如果它是FULL_FLUSH;但是,接收器删除额外的2字节并调用inflate()。

    3. 99%的时间都有效;从某种意义上说,inflate()成功,未压缩的数据确实与压缩前的发送者相同。这是我的期望! 偶尔;但是,这种方法会使接收器处于不良状态,其中每个后续数据包(包括FULL_FLUSH数据包)都无法解压缩。 inflate()返回Z_DATA_ERROR,zlibContext.zstream.msg包含错误的标题检查&#39 ;;虽然我偶尔会收到太远的无效距离'信息。

      我的第一个问题是

        

      我应该期望在数据包成功恢复和膨胀()   在手边使用FULL_FLUSH冲洗模式进行压缩; 即使   之前的数据包丢失了?例如,发件人使用deflate(ctx, SYNC_FLUSH)压缩前3个数据包并发送它们;通过网络一次一个。然后,发送方使用deflate(ctx, FULL_FLUSH)压缩第四个数据包,并通过网络发送。接收器接收分组1和1。 2并成功调用inflate()。然后接收器接收分组4;它(通过序列#)检测到它丢失了数据包3.由于数据包4是使用FULL_FLUSH压缩的,因此接收器期望inflate()成功解压缩数据包。 这是一个有效的假设吗?

      我的第二个问题是

        

      我还需要在接收器中做些什么才能从数据包丢失中恢复并继续解压缩数据包?

2 个答案:

答案 0 :(得分:1)

你的逻辑略有错误。 FULL_FLUSH数据包执行完全刷新。 该数据包之后,状态被刷新。通过处理FULL_FLUSH数据包,您尝试执行刷新 - 但您不能,因为您没有正确的状态来执行刷新。

然而,你可以在同花顺后恢复。因为在刷新之后,刷新状态。

因此,在丢失之后,您不希望处理FULL_FLUSH数据包,因为您没有处理它所需的上下文。但是,该数据包之后,状态已经完全刷新,因此您可以使用 next 数据包恢复通胀。

所以你的丢包逻辑应该是:

  1. 等到收到设置了FULL_FLUSH位的数据包。
  2. 等待下一个数据包。
  3. 如果FULL_FLUSH数据包与此数据包之间没有数据包丢失,则从此数据包开始恢复通胀(带有干净的上下文!)。

答案 1 :(得分:1)

如果在完全刷新后正确地破坏了压缩流,那么是的,随后的新增或重置膨胀实例将始终可解压缩。

完全刷新后,必须调用deflate()直到avail_out不为零,才能发出上一个流的结尾。 之后的内容是您在数据包中添加标记为完全刷新的内容。在完全刷新之后,您可能无法正确定位压缩数据的开始,因为根据您的缓冲区大小,可能会在第一次deflate()调用的大部分时间内完成刷新。

在接收方,确保充气机正在重启并以原始模式解码,这将通过inflateInit2() windowBits等于-15或{{{}}来完成1}}在这种原始的膨胀状态。如果它在99%的时间内工作,或者就此而言,你必须已经这样做了。