gzip으로 압축 된 http 응답을 압축하는 데 문제가 거의 없습니다. 헤더에서 데이터 부분을 분리했지만 gzip 헤더와 메시지에 char *가 null 터미네이터로 사용되는 \ 0 문자가 포함되어 있으므로 첫 번째 질문은 gzipped 덩어리?C - 압축 해제 된 HTTP 응답
청크 내의 여러 위치에서 \ 0 문자가 포함 된 압축 된 gzipped 데이터이기 때문에 strcat, strlen과 같은 문자열 함수를 사용할 수 없습니다.
저는 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;
}
여기에 몇 가지 큰 문제가 있습니다. 수신 한 모든 패킷에 대해 recvData를 할당하고 지 웁니다. 1) 메모리 누수가 발생하고 2) 최종 recvData에 0 묶음과 마지막 패킷이 들어 있음을 의미합니다. 또한 오프셋의 사용은 펑키 한 것 같아요, 그것은 첫 번째 패킷에 대해 업데이 트되지 않습니다. – harald
죄송합니다 ... 1) 프로그램은 recvData에 메모리를 한 번만 할당합니다. 기본적으로 코드를 복사하는 동안 해당 조건을 복사하지 않아서 문제가 없으므로 업데이트 된 코드를 참조하십시오. 2) 오프셋은 일시적으로 3으로 설정되어 사용됩니다 두 번째 memcpy()에서 memcpy()를 쓰지 않는 이유는 memcpy()가 처음부터 memcpy()의 IF 조건에서 데이터에서 헤더를 나눠서 오프셋이 헤더를 제외한 데이터 바이트의 수로 설정되어야한다는 것입니다. bytes 즉, offset = recvBytes-strtidx; 하지만 문제는 첫 번째 memcpy() 복사하는 것입니다 \ 0 chars recvBuff의 gzipped 데이터에서 3 문자를 복사합니다. – Coder
이제 프로그램이 http 응답의 압축을 풉니 다! memcpy()는 \ 0 문자를 복사하고 있었지만 Eclipse 디버거는 전체 gzip 청크를 표시하지 않고 \ 0에서 중단되었습니다. 위 코드를 업데이트했습니다. – Coder