c语言解压http中的gzip文件

这是一篇流水账,记录前两天在解决http中解压gzip数据流程。(写完这篇就可以做其他工作了~~)

目的:c语言解压http的中gzip文件

一、 tcpdump抓包,这条数据包是我试用某app时收到的包,咱们先是用wireshark解析。

c语言解压http中的gzip文件_第1张图片

图上的标号解释下:

1.Content-Encoding: gzip\r\n   指明数据包是gzip;

2.Okhttp走的并不是原生的http请求,因此他在header里面并没有真正的User-Agent,而是“okhttp/版本号”这样的字符串,因为后台需要统计信息,要求传入正确的User-Agent;(这段网上复制的)

3.gzip数据包有1376字节

4.gzip压缩的数据,可以看到数据包的前6字节1f8b08,1F0B代表gzip格式,08代码deflate算法;

5.因为有gzip标识,所以wireshark自动解压出来了gzip数据,如果用printf打印,是乱码,必须解压;

6.同5;

7.这里的字段是我们最终要找的字段,我给打码了,是这个app的账号;

8.gzip有1376字节,解压后的大小为4093字节。


二、c语言找到gzip数据包起始位置

1.从http字段找到“Content-Encoding: gzip”,可以在这里判断http数据是否用gzip压缩过,以 \r\n\r\n结尾的表示http报文结束(gzip是压缩过的数据,紧跟在http结束标志后面)

2.紧跟着的一组ascll码是gzip数据包的大小,xxxxxx\r\n ,这里的\r\n为gzip长度结束;

3.接下来的位置是gzip数据包的起始位置;

好了,到现在gzip起始位置与gzip数据包长度都找到了,一切都好说咯~

//贴一段功能函数,ascll码转十进制
int chrtodec(char chr)
{
	int value=0;
	//先全部将小写转换为大写
	if((chr>='a')&&(chr<='z'))
			chr=chr-32;
	//将字符转化成相应的数字
	if((chr>='0')&&(chr<='9'))
			value=chr-48;
	else if((chr>='A')&&(chr<='Z'))
			value=chr-65+10;
	return value;
}

三、gzip解压

1.方式一,gzip数据写在文件里,在命令行解压这个文件,虽说可以成功,但比较笨拙的赶脚,不推荐。

2.方式二,调用zlib库,在内存里解压,这段代码不是我写的,从某一位网友那里copy过来的,很好用。(详见本文最后几个链接)

/* Gzip uncompress*/
/* 注意:gzip和zip解压大致相同,但是他们的头数据大小不一样,这个得注意,用inflateInit2(&d_stream,47)*/
int
vidpeek_uncompressGzip(unsigned char* pSrc, unsigned int srcSize,char**pOutDest, unsigned int* pOutBufSize)
{
#define OK 0
#define ERR -1
    int ret = OK;
    char* pBuf = pSrc+ (srcSize - 1);
    unsigned int len =*pBuf;
    int uncompressResult;   
    z_stream d_stream;  
    int i = 0;

    printf("#############pSrc 0x%x 0x%x 0x%x 0x%x", pSrc[0], pSrc[1], pSrc[2], pSrc[3]);
    //check gz file,rfc1952 P6
    if((*pSrc !=0x1f)||(*(pSrc+1) != 0x8b))
    {
        printf("\nuncompressGzip non Gzip\n");
        return ERR;
    }
    for(i = 0; i < 3; i++)
    {
        pBuf--;
        len <<= 8;
        len += *pBuf;
    }

    //fortest
    if((len== 0) || (len > 1000000))
    {
        printf("\nuncompressGzip,error gzip!\n");
        return ERR;
    }

    //gzipdecompression start!!!

    d_stream.zalloc =Z_NULL;
    d_stream.zfree =Z_NULL;
    d_stream.opaque = Z_NULL;
    d_stream.next_in =Z_NULL;
    d_stream.avail_in= 0;
    uncompressResult =inflateInit2(&d_stream,47);
    if(uncompressResult!=Z_OK)
    {
        printf("\ninflateInit2 error:%d\n",uncompressResult);
        return uncompressResult;
    }

    d_stream.next_in=pSrc;
    d_stream.avail_in=srcSize;
    d_stream.next_out=(char *)*pOutDest;
    d_stream.avail_out=len;
    uncompressResult =inflate(&d_stream,Z_NO_FLUSH);

    switch(uncompressResult)
    {
        case Z_NEED_DICT:
            uncompressResult = Z_DATA_ERROR;
        case Z_DATA_ERROR:
        case Z_MEM_ERROR:
            (void)inflateEnd(&d_stream);
            return uncompressResult;
    }

   //printf("outlen= %d, total_in= %d, total_out= %d, avail_out= %d@@@@@@@@@@@\n",len, d_stream.total_in, d_stream.total_out, d_stream.avail_out);           

    inflateEnd(&d_stream);
    *pOutBufSize = len-2;
    return ret;
}

四、解析解压成功的数据

根据解压成功数据,找到目标字段,比如 "p":"  ,注意c语言的双引号前面要加"\"。


结果:成功找到gzip中的app账户字段!


参考链接

https://blog.csdn.net/fcryuuhou/article/details/12951279

https://blog.csdn.net/qinggebuyao/article/details/7728520

http://www.openedv.com/forum.php?mod=viewthread&tid=231109


好了,溜了~~~

有缘看到的盆友,欢迎提意见啊!

感谢!大家一起技术进步哟~~





你可能感兴趣的:(linux应用,http,c语言,gzip)