我目前正在用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缓冲,(当它们被连接时)是一个整体请求。
但是:目前,我的客户端(浏览器)仅获得第一个缓冲区的信息。完全没有错误。
我如何完成这项工作,如何在循环中gzip一些缓冲区,以便每次(在循环中)发送它们?
答案 0 :(得分:0)
首先,您需要在每次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流,大多数浏览器仅会解释第一个gzip流。 (这实际上是这些浏览器中的错误,但我不认为它们会得到解决。)
您需要给压缩器至少10到100 KB的磁盘以进行适当的压缩。您需要使用Z_NO_FLUSH
而不是Z_FINISH
直到您要发送的最后一个buff
为止。然后,您使用Z_FINISH
。同样,请看一下示例并阅读评论。