0

我正在编写一个小型服务器 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()时缓冲区具有正确的值
主要思想是我不能直接压缩文件,因为我需要对实际程序中的结果进行内存操作。

4

1 回答 1

3

你有很多问题:

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

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);
于 2014-02-25T15:52:53.400 回答