天天看點

linux gzip 解壓 函數,擷取http的gzip内容,并解壓

問題:

入問題,問題答案立即呈現在您眼前!

尋找gzip

擷取一個網頁資料傳回的編碼類型是gzip,我該怎麼解壓縮

HTTP頭擷取?

如何用vb擷取網絡上的xml檔案,并解析内容

關于GZIP的解碼

怎樣解gzip的壓縮

請問Wininet是否可以進行Gzip的http傳輸,尤其是post的時候!如果可以如何實作?

關于GZIP格式解壓縮HTTP資料包的問題,我使用ZLIB為什麼必須先儲存檔案,記憶體解壓縮出錯

無法擷取$_SERVER["HTTP_REFERER"]

關于GZIP的問題,高分求解!!

.....

等都是關于gzip解壓的

問題:

提取http的gzip内容,并解壓。

關鍵點:

1 提取http資料包的内容,主要是gzip格式的

2 資料包的重組

3 在記憶體中解壓gzip資料

這兩個周過來,都是在網上過來的,得到網友的幫助不少,很是感激,為了不讓這個問題繼續困擾後來的un_gziper,特寫此文。

1 資料包記憶體的提取:

關鍵的地方是找到gzip記憶體的開始位置以及如何确定gzip内容的大小

開始位置:“Content-Encoding: gzip\r\n\r\n”

gzip大小:“Content-Length:”後面的就是了

2 資料包的重組,一般網頁的内容很少是一個資料包可以裝得下的,是以都得進行gzip之後再用多個資料包進行傳輸

關鍵的地方是:

get請求資料包的ack和seq與http傳回資料包的ack,seq有密切的聯系:

舉例說明:

get請求:ack=0,seq=0

http1:seq=0,ack=584

http2: seq=1420,ack=584

...

簡單的分析說明可以看出,我們的算法設計:

首先得到get請求的ack,傳回的資料包的seq等于這個值,同時記下這個資料包的ack,後面進行分包發送的http的資料包的ack都是這個值,這個是關鍵點之一,同時綜合

Content-Length就可以得到gzip的全部内容。

至此,原始資料提取完畢,該是如何解壓的問題了

3解壓gzip

我做了上面的1,2步以後将内容儲存到檔案裡面,用gzip指令可以打開,驗證了資料的完整性。

而後我采用了zlib提供的uncompress函數,和大多數的網友一樣,都是犯了一個緻命的錯誤,沒有仔細的閱讀zlib的文檔!導緻一次次無謂的識别!

事實上zlib格式和gzib格式是有差别的,而uncompress是用來解壓zlib格式檔案的,這就是為什麼會出現用compress函數壓縮的資料,在記憶體中可以直接用uncompress函數進行解壓的,而就不能解壓gzip資料的問題!

後來測試了zlib包裡面的example例子,算是對zlib有了一點點的了解,應該用inflate類函數進行解壓!

當然這樣遇到了問題,格式不對!

後來在網上看到的文章:gzip格式用inflate函數還不行,必需要用inflateInit2(&strm, 47); !!!!!!!!!!!!!!!!!!

問題解決!

這裡借用那位網友的源代碼,同時對他表示感謝!

int inflate_read(char *source,int len,char **dest,int gzip)

{

int ret;

unsigned have;

z_stream strm;

unsigned char out[CHUNK];

int totalsize = 0;

strm.zalloc = Z_NULL;

strm.zfree = Z_NULL;

strm.opaque = Z_NULL;

strm.avail_in = 0;

strm.next_in = Z_NULL;

if(gzip)

ret = inflateInit2(&strm, 47);

else

ret = inflateInit(&strm);

if (ret != Z_OK)

return ret;

strm.avail_in = len;

strm.next_in = source;

do {

strm.avail_out = CHUNK;

strm.next_out = out;

ret = inflate(&strm, Z_NO_FLUSH);

assert(ret != Z_STREAM_ERROR);

switch (ret) {

case Z_NEED_DICT:

ret = Z_DATA_ERROR;

case Z_DATA_ERROR:

case Z_MEM_ERROR:

inflateEnd(&strm);

return ret;

}

have = CHUNK - strm.avail_out;

totalsize += have;

*dest = realloc(*dest,totalsize);

memcpy(*dest + totalsize - have,out,have);

} while (strm.avail_out == 0);

(void)inflateEnd(&strm);

return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;

}

後記,這個過程是痛苦的,但也是幸福的!

這裡我發起一個小小的倡議,對所有關注gzip解壓的問題的網友:

我們都遇到了一個問題就是zlib的文檔都是英文的,有個别網友翻譯了開頭的一小部分,但是這是不夠的!

是以,我希望有興趣的朋友可以一起來幫zlib的文檔翻譯成為中文!

有興趣的可以加我!

閱讀(2738) | 評論(0) | 轉發(0) |