C.循环压缩+发送(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’ed缓冲区(当它们被连接时)是一个全身请求。

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

我如何实现这项工作,如何在循环中gzip一些缓冲区,这样我每次都可以发送它们(在循环中)?

首先,您需要在每次deflate()调用后对生成的deflate数据执行某些操作。 您的代码会丢弃内循环中生成的压缩数据。 从这个例子来看,在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的千字节,以便进行适当的压缩。 你需要使用Z_NO_FLUSH而不是Z_FINISH直到你想要发送你的最后一个buff 。 然后你使用Z_FINISH 。 再次,看看示例并阅读评论。