【问题标题】:Compressing data before sending it - controll characters?在发送数据之前压缩数据 - 控制字符?
【发布时间】:2013-12-27 13:46:14
【问题描述】:

在多人游戏设置中,我打算在发送之前使用 zlib 压缩较大的字符串。我将生成的数据放回字符串中,这些字符串将使用 TCP 作为字节流发送。

我的问题是,我还需要将控制字符放入字符串中。例如,我需要将原始字符串长度(纯文本)添加到压缩字符串的前面,并使用一些符号将其与压缩数据分开,例如“|”。

但是我找不到知道哪些字节是实际内容以及哪些字节是控制字符的方法。是否有任何字符是 zlib-compressed-string 永远不会包含的(除了 0,我不能使用它,因为它标志着 c-string 的结尾)我可以用来分隔“元数据”和“压缩数据”?

【问题讨论】:

  • 为什么需要把长度和剩余数据分开??
  • 为什么需要纯文本的长度?使用二进制格式不是更简单吗?
  • 把压缩数据的长度放在前面,知道你的数据什么时候结束,什么时候开始一个新的消息类型?
  • 我使用了zlib.h中定义的compress和uncompress函数。后者需要一个长度正确的缓冲区来生成原始字符串,为了简单起见,我想将其发送出去。由于我为发送和接收数据而实现的结构当前使用字符串(我需要其他值),因此我想将压缩数据打包成这样的字符串。但如果有更好的方法,我愿意接受建议。 “使用二进制格式”是指始终使用前(两个)字节来包含长度吗?
  • @user1781290,这就是我想做的,是的。但我不知道如何将长度与实际数据分开......

标签: c++ c tcp zlib


【解决方案1】:

不,没有不能包含在 zlib 流中的字节值。然而,zlib 流是自行终止的。只需使用inflate() 解压流,当它返回Z_STREAM_END 时,您会发现结束。 inflate() 未使用的字节是紧接在 zlib 流之后的下一个字节。解压完成后,您既知道流中有多少压缩数据字节,也知道生成了多少未压缩字节。

如果您只是简单地处理整个流,并按顺序嵌入 zlib 流,则无需在任何地方存储压缩或未压缩的长度。该信息是 zlib 数据中固有的。如果您需要非顺序地处理流,或者希望在 zlib 数据之后访问流中的其他数据而无需解压缩 zlib 流,则只需要存储此类数据。

【讨论】:

  • 嗯,我不知道可以从流中导出长度。然后我需要切换到 inflate(),不过,到目前为止我还没有这样做。压缩流中也可以有零吗?因为字符串是以零结尾的 - 我可能会遇到问题。
  • 是的,可以有零。 所有字节值将出现在足够长的流中。如果您知道 zlib 流从哪里开始,那么就不会有混淆。
【解决方案2】:

如果您同时控制压缩 blob 的创建和解压缩,则可以将大小添加到压缩数据(可能通过在缓冲区的开头保留一些字节),然后在解压缩时跳过大小并传递指针压缩数据到解压缩实用程序。这样您就不必担心将压缩数据与大小混淆:解压缩代码永远不会看到携带大小信息的字节。

【讨论】:

  • 是的,这可以满足我的要求。然后我可以将压缩数据之后字符串中的所有内容视为“普通”ascii字符串。谢谢!
【解决方案3】:

你是如何进行压缩的?如果您正在管道输出 通过外部程序,您无能为力,但如果 您正在使用内部的东西,例如压缩流缓冲区, 你应该能够输出到原来的streambuf 必要的。过滤来自boost::iostream 的流,用于 例如,您可以写入长度,然后推送压缩 流,写入要压缩的数据,然后弹出 压缩流,并继续写入纯文本。 (您可以 在改变之前必须在这里和那里插入一个明智的同花 过滤器堆栈。)或者你应该能够压缩部件 你想压缩成一个缓冲区,并使用 std::ostream::write 输出它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多