我正在编写一个小型服务器 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(¶llel,NULL,reponse,(void *)newsockfd);
}
}
这不起作用,因为当我启动 telnet 192.168.0.20 80
时,没有任何打印。
根据 GDB 中的逐步执行,调用 write() 时缓冲区具有正确的值
主要思想是我不能直接压缩文件,因为我需要在实际程序中对结果进行内存操作。
最佳答案
你有很多问题:
- 您正在调用
sscanf()
以在开始时从空缓冲区中读取数据。我认为您打算使用sprintf()
将测试数据写入缓冲区(但实际上,使用snprintf()
以避免缓冲区溢出)。 - 您对
compress2()
函数的输入使用与输出相同的缓冲区。文档不清楚这是否受支持,所以我认为这不是为了安全起见。 - 关于你的输出缓冲区有多大,你在向 zlib 撒谎。你告诉它你的缓冲区是
compressBound(...)
字节,而实际上它只有 4700 字节。因为不可能压缩每个可能的数据流,所以有一些字节序列在压缩后会变大,所以如果你对它撒谎,zlib 可能会尝试溢出你的缓冲区,然后可能导致段错误。如果您至少告诉它您的缓冲区有多大的真相,它会因该原因而失败,而不是尝试越界读/写内存。 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/