c - 如何使用 zlib 为 HTTP 压缩 HTTP 响应?

标签 c zlib content-encoding

我正在编写一个小型服务器 http,它总是发送他生成的 html 页面(它丢弃客户端请求)。这是一个更大程序的一部分

我想使用内容编码来最小化本地带宽使用...

我开始尝试这个例子:

#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include <zlib.h>
#define CHUNK 1048576

const char * restrict UrList[] = {"An", "example", "of", "random","ASCII string"};

void reponse(int newsockfd)
{
    char * buffer=calloc(sizeof(char),4700);
    srand(time(0));
    sscanf(buffer,"<!DOCTYPE html>\ // hopfully this is a test as I don't hard code like this in real programs...
<html>\
<head>\
    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\
    <title color=\"white\">%s</title>\
    <body align=\"center\" valign=\"center\" >\
        <button onclick=\"launchFullscreen(document.body);\">%s!</button>\
    </body>\
</html>\0",UrList[(rand()%3)]);
    size_t inputLen = strlen(buffer);
    uLong maxOutputLen = compressBound(inputLen);
    char * destbuffer=malloc(inputLen);
    compress2(destbuffer,&maxOutputLen,buffer,inputLen,Z_BEST_COMPRESSION);
    sprintf(buffer,"200 OK\n\
Server: Serveur personalisé ayant pour but d'empêcher les accès au nom de domaines interdits de manière efficace\n\
X-Powered-By: GCC 4.8.1\n\
Cache-Control: must-revalidate, post-check=0, pre-check=0\n\
ETag: \"1390786010\"\n\
Content-Language: fr\n\
Vary: Accept-Encoding\n\
Content-Type: text/html; charset=UTF-8\n\
\n\
%s \0",destbuffer);
    write(newsockfd,buffer,inputLen);
    free((void *)buffer);
    free((void *)destbuffer);
}

void main()
{
    struct  sockaddr_in6 client_address, server_address;
    int clilen,server_handle=socket(PF_INET6, SOCK_STREAM, 0);

    if (server_handle < 0)
        perror("Unable to create socket.");
    server_address.sin6_family = AF_INET6;
    server_address.sin6_addr = in6addr_any;
    server_address.sin6_port = 0x5000; // port 80
    if ( bind(server_handle, (struct sockaddr *)&server_address, sizeof( server_address )) < 0)
        perror("Unable to bind.");
    listen(server_handle,1310730);
    clilen=sizeof(client_address);
    while(1)
    {
        // variables locales
        pthread_t parallel;

        int newsockfd=accept(server_handle, (struct sockaddr *) &client_address, &clilen);
        pthread_create(&parallel,NULL,reponse,(void *)newsockfd);
    }
}

这不起作用,因为当我启动 telnet 192.168.0.20 80 时,没有任何打印。

根据 GDB 中的逐步执行,调用 write() 时缓冲区具有正确的值
主要思想是我不能直接压缩文件,因为我需要在实际程序中对结果进行内存操作。

最佳答案

你有很多问题:

  1. 您正在调用 sscanf() 以在开始时从空缓冲区中读取数据。我认为您打算使用 sprintf() 将测试数据写入缓冲区(但实际上,使用 snprintf() 以避免缓冲区溢出)。
  2. 您对 compress2() 函数的输入使用与输出相同的缓冲区。文档不清楚这是否受支持,所以我认为这不是为了安全起见。
  3. 关于你的输出缓冲区有多大,你在向 zlib 撒谎。你告诉它你的缓冲区是 compressBound(...) 字节,而实际上它只有 4700 字节。因为不可能压缩每个可能的数据流,所以有一些字节序列在压缩后会变大,所以如果你对它撒谎,zlib 可能会尝试溢出你的缓冲区,然后可能导致段错误。如果您至少告诉它您的缓冲区有多大的真相,它会因该原因而失败,而不是尝试越界读/写内存。
  4. compress2() 的第二个参数是一个指向变量的指针,该变量既是输入参数也是输出参数。在输入时,它包含输出缓冲区的最大 大小,在输出时,它接收压缩数据的实际 大小。您正在传递一个整数值(不是指针)并忽略编译器关于整数和指针类型之间转换的警告。 听听你的编译器!

以下是使用单独的输入和输出缓冲区正确调用 compress2() 函数的方法:

// Error checking elided for expository purposes
const char *inputBuf = "the data to compress...";
size_t inputLen = strlen(inputBuf);

// Compute the maximum size of the compressed output and allocate an output
// buffer for it -- note that this will be LARGER than the input size
uLong maxOutputLen = compressBound(inputLen);
char *outputBuf = malloc(maxOutputLen);

// Compress the data and receive the compressed data size
uLong compressedLen = maxOutputLen;
int result = compress2(outputBuf, &compressedLen, inputBuf, inputLen, Z_BEST_COMPRESSION);

// Use the compressed data
...

free(outputBuf);

关于c - 如何使用 zlib 为 HTTP 压缩 HTTP 响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22018774/

相关文章:

c - 只有一条消息通过管道

ubuntu - zlib uncompress 在 Ubuntu 10.10 x64 (g++ -m64) 上返回 -5

C++ 从 std::vector 膨胀 zlib

c++ - 查找 zlib 压缩流的结尾

Java:HttpResponse header 从来没有 "Content-Encoding",但确实有 "Vary: Accept-Encoding"

performance - 浏览器可能无法理解 gzip 内容的原因

c - 在编译时和/或运行时检测正在运行的 Linux 发行版?

c - Borland C++ 3.1 中的链接图形库

c - 无法在 Mac 上使用 gsl 进行编译

c# - Content-Transfer-Encoding 是 HTML header 吗?