C.循环压缩+发送(gzip) ZLIB

标签 c http compression gzip zlib

我目前正在用 C 语言构建一个 HTTP 服务器。

请注意这段代码:

  #define CHUNK 0x4000
  z_stream strm;
  unsigned char out[CHUNK];
  int ret;
  char buff[200];

  strm.zalloc = Z_NULL;
  strm.zfree = Z_NULL;
  strm.opaque = Z_NULL;

  int windowsBits = 15;
  int GZIP_ENCODING = 16;

  ret = deflateInit2(&strm, Z_BEST_SPEED, Z_DEFLATED, windowsBits | GZIP_ENCODING, 1, 
                     Z_DEFAULT_STRATEGY);
  fill(buff); //fill buff with infos

  do {
  strm.next_in = (z_const unsigned char *)buff;
  strm.avail_in = strlen(buff);
      do {
        strm.avail_out = CHUNK;
        strm.next_out = out;
        ret = deflate(&strm, Z_FINISH);
       } while (strm.avail_out == 0);

  send_to_client(out); //sending a part of the gzip encoded string
  fill(buff);
  }while(strlen(buff)!=0);

这个想法是:我试图一个接一个地发送经过 gzip 压缩的缓冲区,(当它们连接起来时)是一个整体请求。

但是:目前,我的客户端(浏览器)仅获取第一个缓冲区的信息。但完全没有错误。

我如何完成这项工作,如何在循环内压缩一些缓冲区,以便我可以每次(在循环中)发送它们?

最佳答案

首先,您需要在每次 deflate() 调用后对生成的 deflate 数据执行一些操作。您的代码会丢弃内部循环中生成的压缩数据。来自 this example ,在 deflate() 之后,您需要类似以下内容:

        have = CHUNK - strm.avail_out;
        if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
            (void)deflateEnd(&strm);
            return Z_ERRNO;
        }

这就是您的 send_to_client 需要的位置,发送 have 字节。

就您而言,您的 CHUNK 比 buff 大得多,该循环始终只执行一次,因此您不会丢弃任何数据。然而,这只是因为 Z_FINISH 才发生,因此当您进行下一次修复时,您将使用当前代码丢弃数据。

其次,每次输入不超过 199 个字节后,您就会完成 deflate() 流。这将极大地限制您可以获得的压缩程度。此外,您正在发送单独的 gzip 流,大多数浏览器只会解释第一个流。 (这实际上是这些浏览器中的一个错误,但我不认为它们会被修复。)

您需要为压缩器提供至少 10 到 100 KB 的空间来工作,以获得良好的压缩效果。您需要使用 Z_NO_FLUSH 而不是 Z_FINISH,直到到达您想要发送的最后一个 buff。然后使用Z_FINISH。再次,看一下示例并阅读注释。

关于C.循环压缩+发送(gzip) ZLIB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51322449/

相关文章:

c - 如何从 printf 输出中删除最后一个空格

c - 将窗口句柄传递给 C 中的线程。 (WIN32 API)

http - 在 J2ME 中使用多个 hppt 连接上传大文件

compression - 使用--rsyncable选项像gzip一样使zstd压缩文件“rsyncable”

c - 透明的 SQLite 数据压缩

c++ - 如何添加第三方库的路径? - Eclipse/Arduino

c - 为什么这个程序不停止?

c# - HttpWebResponse 的编码问题

java - Spring:从 Web 应用程序线程子线程(来自 ThreadPool)访问请求( session )作用域 Bean

c# - 您能否预压缩数据文件以便稍后插入到 zip 文件中以提高性能?