У меня мало проблем с распаковкой HTTP-ответа gzip, я отделил часть данных от заголовков, но его заголовок gzip и сообщение содержат символы \ 0, которые char * принимает как нулевой терминатор, поэтому первый вопрос - как извлечь gzipped chunk?
Я не могу использовать строковые функции, такие как strcat, strlen, потому что это сжатые сжатые данные, которые содержат символы \ 0 в разных местах фрагмента.
Я использовал libcurl, но он относительно медленнее, чем сокеты C.
Вот некоторая часть примера ответа:
HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Type: text/html; charset=utf-8
P3P: CP="NON UNI COM NAV STA LOC CURa DEVa PSAa PSDa OUR IND"
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 12605
Date: Mon, 05 Mar 2012 11:46:30 GMT
Connection: keep-alive
Set-Cookie: _FP=EM=1; expires=Wed, 05-Mar-2014 11:46:29 GMT; domain=.bing.com; path=/
����ՠ����AU��o�
Пример кода:
#define MAXDATASIZE 1024
char *recvData; // Holds entire gzip data
char recvBuff[MAXDATASIZE]; // Holds gzip chunk
int offset=0;
while(1){
recvBytes = recv(sockfd, &recvBuff, MAXDATASIZE-1, 0);
totalRecvBytes += recvBytes;
// get content length, this runs first time only as required
if(!clfnd){
regi = regexec(&clregex, &recvBuff, 3, clmatch, 0);
if(!regi){
strncpy(clarr, recvBuff + clmatch[2].rm_so, clmatch[2].rm_eo-clmatch[2].rm_so);
clarr[clmatch[2].rm_eo-clmatch[2].rm_so] = '\0';
cl = atoi(clarr);
clfnd=1;
regfree(&clregex);
recvData = malloc(cl * sizeof(char));
memset(recvData, 0, sizeof recvData);
}
}
// get data part from 1st iteration, furthur iterations contain only data
if(!datasplit){
int strtidx;
char *datastrt = strstr(&recvBuff, "\r\n\r\n");
if(datastrt != NULL){
strtidx = datastrt - recvBuff + 4;
memcpy(recvData, recvBuff + strtidx, recvBytes-strtidx);
datasplit=1;
offset = recvBytes-strtidx;
}
}
else{
memcpy(recvData + offset, recvBuff, recvBytes);
offset += recvBytes;
}
if (offset >= cl)
break;
}
char *outData = malloc(offset*4 * sizeof(char));
memset(outData, 0, sizeof outData);
int ret = inf(recvData, offset, outData, offset*4);
Функция надувания:
int inf(const char *src, int srcLen, const char *dst, int dstLen){
z_stream strm;
strm.zalloc=NULL;
strm.zfree=NULL;
strm.opaque=NULL;
strm.avail_in = srcLen;
strm.avail_out = dstLen;
strm.next_in = (Bytef *)src;
strm.next_out = (Bytef *)dst;
int err=-1, ret=-1;
err = inflateInit2(&strm, MAX_WBITS+16);
if (err == Z_OK){
err = inflate(&strm, Z_FINISH);
if (err == Z_STREAM_END){
ret = strm.total_out;
}
else{
inflateEnd(&strm);
return err;
}
}
else{
inflateEnd(&strm);
return err;
}
inflateEnd(&strm);
printf("%s\n", dst);
return err;
}