在實際應用中經常會遇到要壓縮數據的問題,常見的壓縮格式有zip和rar,而
Linux下那就更多了,bz2,gz,xz什么的都有,單單Linux下的解壓和壓縮命令就有好多呢?沒有什么好不好的。查了資料,應該是zlib這個
比較簡單好用。應用也廣,所以就準備用這個了。
下載Zlib庫,地址:?http://zlib.net
/zlib128.zip 用wget下載,然后再用unzip解壓一下,然后就像一般軟件一樣 ./configure &&
make && make install .(注意要root權限)
下面這個是安裝信息
cp?libz.a?
/
usr
/
local
/
lib
chmod?
644
?
/
usr
/
local
/
lib
/
libz.a
cp?libz.so.
1.2
.
8
?
/
usr
/
local
/
lib
chmod?
755
?
/
usr
/
local
/
lib
/
libz.so.
1.2
.
8
cp?zlib.
3
?
/
usr
/
local
/
share
/
man
/
man3
chmod?
644
?
/
usr
/
local
/
share
/
man
/
man3
/
zlib.
3
cp?zlib.pc?
/
usr
/
local
/
lib
/
pkgconfig
chmod?
644
?
/
usr
/
local
/
lib
/
pkgconfig
/
zlib.pc
cp?zlib.h?zconf.h?
/
usr
/
local
/
include
chmod?
644
?
/
usr
/
local
/
include
/
zlib.h?
/
usr
/
local
/
include
/
zconf.h
寫一個簡單的例子測試一下,注意編譯的時候要加入 -lz 這個庫
#include?
<
stdio.h
>
#include?
<
zlib.h
>
int
?main(
int
?argc,
char
?
**
args)
{
????
/*
原始數據
*/
????unsigned?
char
?strsrc[]
=
"
這些是測試數據。123456789?abcdefghigklmnopqrstuvwxyz\n\t\0abcdefghijklmnopqrstuvwxyz\n
"
;?
//
包含\0字符
????unsigned?
char
?buf[
1024
]
=
{
0
};
????unsigned?
char
?strdst[
1024
]
=
{
0
};
????unsigned?
long
?srclen
=
sizeof
(strsrc);
????unsigned?
long
?buflen
=
sizeof
(buf);
????unsigned?
long
?dstlen
=
sizeof
(strdst);
????
int
?i;
????FILE?
*
?fp;
????printf(
"
源串:
"
);
????
for
(i
=
0
;i
<
srclen;
++
i)
????{
????????printf(
"
%c
"
,strsrc[i]);
????}
????printf(
"
原串長度為:%ld\n
"
,srclen);
????printf(
"
字符串預計算長度為:%ld\n
"
,compressBound(srclen));
????
//
壓縮
????compress(buf,
&
buflen,strsrc,srclen);
????printf(
"
壓縮后實際長度為:%ld\n
"
,buflen);
????
//
解壓縮
????uncompress(strdst,
&
dstlen,buf,buflen);
????printf(
"
目的串:
"
);
????
for
(i
=
0
;i
<
dstlen;
++
i)
????{
????????printf(
"
%c
"
,strdst[i]);
????}
????
return
?
0
;
}
各個API
?1?//把源緩沖壓縮成到目的緩沖,一個函數就完成了
?2?int?compress?(Bytef?*dest,?uLongf?*destLen,?const?Bytef?*source,?uLong?sourceLen);
?3?
?4?//功能和compress函數一樣,多了一個參數可以指定壓縮質量和壓縮數度之間的關系(0-9)。要想得到高的壓縮比就要多花時間
?5?int?compress2?(Bytef?*dest,?uLongf?*destLen,const?Bytef?*source,?uLong?sourceLen,int?level);
?6?
?7?//計算需要的緩沖區長度.?假設你在壓縮之前就想知道你的產度為?sourcelen?的數據壓縮后有多大,?可調用這個函數計算一下,這個函數并不能得到精確的結果,但是它可以保證實際輸出長度肯定小于它計算出來的長度
?8?uLong?compressBound?(uLong?sourceLen);
?9?
10?//解壓縮
11?int?uncompress?(Bytef?*dest,?uLongf?*destLen,const?Bytef?*source,?uLong?sourceLen);
處理gz后綴的壓縮文件。
壓縮字符串到test.gz
?1?#include?<stdio.h>
?2?#include?<zlib.h>
?3?
?4?int?main(int?argc,char?**args)
?5?{
?6?????gzFile?file;
?7?????char?str[]="testtest";
?8?????file=gzopen("test.gz","wb");
?9?????if(NULL==file)
10?????????perror("Can't?open?file");
11?????gzsetparams(file,2,0);
12?????gzwrite(file,str,sizeof(str));
13?????gzclose(file);
14?????return?0;
15?}
解壓test.gz
?1?#include?<stdio.h>
?2?#include?<zlib.h>
?3?
?4?int?main(int?argc,char?**args)
?5?{
?6?????gzFile?file;
?7?????char?str[64]={0};
?8?????file=gzopen("test.gz","rb");
?9?????if(NULL==file)
10?????????perror("Can't?open?file");
11?????gzread(file,str,10);
12?????printf("從文件中讀取到的字符:%s.\n",str);
13?????gzclose(file);
14?????return?0;
15?}
對于test.gz這個文件如果不知道是否正確,可以使用系統命令zcat進
行查看。還有一個問題就是個壓縮包只能解壓出一個文件,是不可能存在多個文件的。 這是GZIP的特性決定了的。
通常,都是把多個文件用tar先壓成一個包,然后在gzip。這就是為什么下載的軟件源碼包大多都是 .tar.gz 這樣的格式。
對于gz文件處理的API
?1?
//注意下面介紹到的處理函數,跟一般文件的處理函數是相似的,效果也是差不多的。
?2?
typedef?voidp?gzFile;
?3?
?4?
//打開一個gzip文件進行讀/寫,mode和fopen("rb"或"?wb")一樣.也可以包括壓縮級別如:"wb9",或著一個策略"f"作為過濾數據"wb6f",?"h"是為了"huffman"?壓縮,如:"wb1h".gzopen用于讀一個沒有gzip格式的文件.gzread直接從沒有解壓縮的文件中讀數據.如果文件不能被打開或是沒有足夠的內存,gzopen將返回NULL.
?5?
gzFile?gzopen(const?char?*path,const?char?*mode);
?6?
?7?
//根據文件描述符打開一個gz文件
?8?
gzFile?gzdopen?(int?fd,?const?char?*mode);
?9?
10?
//動態更新壓縮等級和壓縮格式?成功返回Z_OK?否則返回Z_STREAM_ERROR
11?
int?gzsetparams?(gzFile?file,?int?level,?int?strategy);
12?
13?
//讀取所給的個數len字節。從壓縮文件中讀取解壓后的字符的個數。?如果file不是gzip格式,那么就讀取實際的字節個數,而不是解壓后的實際個數。成功返回所讀取的個數,0表示文件結束,-1表示錯誤。
14?
//英文原文?Reads?the?given?number?of?uncompressed?bytes?from?the?compressed?file.If?the?input?file?was?not?in?gzip?format,?gzread?copies?the?given?number?of?bytes?into?the?buffer.
15?
int?gzread?(gzFile?file,voidp?buf,?unsigned?int?len);
16?
17?
//寫入所給長度的buf字符到file中?成功返回所寫入的字符個數,0表示寫入失敗
18?
int?gzwrite(gzFile?file,?voidp?buf,unsigned?int?len);
19?
20?
//可以看到下面介紹到的所有函數都跟我們處理普通的文件一樣,把函數的gz換成f,是不是就熟悉了許多?大概就是這樣吧
21?
int?gzprintf(gzFile?file,const?char?*format,?
);
22?
int?gzputs(gzFile?file,const?char?*s);
23?
char?*?gzgets(gzFile?file,?char?*buf,int?len);
24?
int?gzputc(gzFile?file,int?c);
25?
int?gzgetc(gzFile?file);
26?
int?gzungetc(int?c,gzFile?file);
27?
int?gzflush?(gzFile?file,int?flush);
28?
int?gzseek?(gzFile?file,z_off_t?offset,?int?whence);
29?
int?gzrewind(gzFile?file);
30?
z_off_t?gztell(gzFile?file);
31?
int?gzeof(gzFile?file);
32?
int?gzdirect(gzFile?file);
33?
int?gzclose(gzFile?file);
34?
const?char?*?gzerror(gzFile?file,?int?*errnum);
35?
void?gzclearerr(gzFile?file);
計算校驗碼
?1?uLong?adler32?(uLong?adler,const?Bytef?*buf,?uInt?len);
?2?//使用方法如下
?3?uLong?adler=adler32(0L,Z_NULL,0);
?4?while(read_buffer(buffer,?length)?!=EOF)
?5?{
?6?????adler=adler32(adler,buffer,length);
?7?}
?8?if(adler?!=?original_adler)
?9?????error();
10?
11?uLong?crc32?(uLong?crc,const?Bytef?*buf,uInt?len);
12?//使用方法如下
13?uLong?crc?=?crc32(0L,Z_NULL,0);
14?while(read_buffer(buffer,length)!=EOF)
15?{
16?????crc=crc32(crc,buffer,length);
17?}
18?if(crc?!=?original_crc)
19?????error();
最后是z_stream這個結構了
?1?typedef?struct?z_stream_s?{
?2?????Bytef????*next_in;??/*?next?input?byte?*/
?3?????uInt?????avail_in;??/*?number?of?bytes?available?at?next_in?*/
?4?????uLong????total_in;??/*?total?nb?of?input?bytes?read?so?far?*/
?5?
?6?????Bytef????*next_out;?/*?next?output?byte?should?be?put?there?*/
?7?????uInt?????avail_out;?/*?remaining?free?space?at?next_out?*/
?8?????uLong????total_out;?/*?total?nb?of?bytes?output?so?far?*/
?9?
10?????char?????*msg;??????/*?last?error?message,?NULL?if?no?error?*/
11?????struct?internal_state?FAR?*state;?/*?not?visible?by?applications?*/
12?
13?????alloc_func?zalloc;??/*?used?to?allocate?the?internal?state?*/
14?????free_func??zfree;???/*?used?to?free?the?internal?state?*/
15?????voidpf?????opaque;??/*?private?data?object?passed?to?zalloc?and?zfree?*/
16?
17?????int?????data_type;??/*?best?guess?about?the?data?type:?binary?or?text?*/
18?????uLong???adler;??????/*?adler32?value?of?the?uncompressed?data?*/
19?????uLong???reserved;???/*?reserved?for?future?use?*/
20?}?z_stream;
1?deflateInit()?+?deflate()?+?deflateEnd()
2??//3個函數結合使用完成壓縮功能,具體用法看?example.c?的?test_deflate()函數.?其實compress()?函數內部就是用這3個函數實現的
3??
4??inflateInit()?+?inflate()?+?inflateEnd()
5??//上面類似,完成解壓縮功能.
6?
7?
下面給出一個example方面查看,了解函數的用法,不過一般應用程序用到上面的函數即可。
??1?/*?zpipe.c:?example?of?proper?use?of?zlib's?inflate()?and?deflate()
??2????Not?copyrighted?--?provided?to?the?public?domain
??3????Version?1.4??11?December?2005??Mark?Adler?*/
??4?
??5?/*?Version?history:
??6????1.0??30?Oct?2004??First?version
??7????1.1???8?Nov?2004??Add?void?casting?for?unused?return?values
??8??????????????????????Use?switch?statement?for?inflate()?return?values
??9????1.2???9?Nov?2004??Add?assertions?to?document?zlib?guarantees
?10????1.3???6?Apr?2005??Remove?incorrect?assertion?in?inf()
?11????1.4??11?Dec?2005??Add?hack?to?avoid?MSDOS?end-of-line?conversions
?12??????????????????????Avoid?some?compiler?warnings?for?input?and?output?buffers
?13??*/
?14?
?15?#include?<stdio.h>
?16?#include?<string.h>
?17?#include?<assert.h>
?18?#include?"zlib.h"
?19?
?20?#if?defined(MSDOS)?||?defined(OS2)?||?defined(WIN32)?||?defined(__CYGWIN__)
?21?#??include?<fcntl.h>
?22?#??include?<io.h>
?23?#??define?SET_BINARY_MODE(file)?setmode(fileno(file),?O_BINARY)
?24?#else
?25?#??define?SET_BINARY_MODE(file)
?26?#endif
?27?
?28?#define?CHUNK?16384
?29?
?30?/*?Compress?from?file?source?to?file?dest?until?EOF?on?source.
?31????def()?returns?Z_OK?on?success,?Z_MEM_ERROR?if?memory?could?not?be
?32????allocated?for?processing,?Z_STREAM_ERROR?if?an?invalid?compression
?33????level?is?supplied,?Z_VERSION_ERROR?if?the?version?of?zlib.h?and?the
?34????version?of?the?library?linked?do?not?match,?or?Z_ERRNO?if?there?is
?35????an?error?reading?or?writing?the?files.?*/
?36?int?def(FILE?*source,?FILE?*dest,?int?level)
?37?{
?38?????int?ret,?flush;
?39?????unsigned?have;
?40?????z_stream?strm;
?41?????unsigned?char?in[CHUNK];
?42?????unsigned?char?out[CHUNK];
?43?
?44?????/*?allocate?deflate?state?*/
?45?????strm.zalloc?=?Z_NULL;
?46?????strm.zfree?=?Z_NULL;
?47?????strm.opaque?=?Z_NULL;
?48?????ret?=?deflateInit(&strm,?level);
?49?????if?(ret?!=?Z_OK)
?50?????????return?ret;
?51?
?52?????/*?compress?until?end?of?file?*/
?53?????do?{
?54?????????strm.avail_in?=?fread(in,?1,?CHUNK,?source);
?55?????????if?(ferror(source))?{
?56?????????????(void)deflateEnd(&strm);
?57?????????????return?Z_ERRNO;
?58?????????}
?59?????????flush?=?feof(source)???Z_FINISH?:?Z_NO_FLUSH;
?60?????????strm.next_in?=?in;
?61?
?62?????????/*?run?deflate()?on?input?until?output?buffer?not?full,?finish
?63????????????compression?if?all?of?source?has?been?read?in?*/
?64?????????do?{
?65?????????????strm.avail_out?=?CHUNK;
?66?????????????strm.next_out?=?out;
?67?????????????ret?=?deflate(&strm,?flush);????/*?no?bad?return?value?*/
?68?????????????assert(ret?!=?Z_STREAM_ERROR);??/*?state?not?clobbered?*/
?69?????????????have?=?CHUNK?-?strm.avail_out;
?70?????????????if?(fwrite(out,?1,?have,?dest)?!=?have?||?ferror(dest))?{
?71?????????????????(void)deflateEnd(&strm);
?72?????????????????return?Z_ERRNO;
?73?????????????}
?74?????????}?while?(strm.avail_out?==?0);
?75?????????assert(strm.avail_in?==?0);?????/*?all?input?will?be?used?*/
?76?
?77?????????/*?done?when?last?data?in?file?processed?*/
?78?????}?while?(flush?!=?Z_FINISH);
?79?????assert(ret?==?Z_STREAM_END);????????/*?stream?will?be?complete?*/
?80?
?81?????/*?clean?up?and?return?*/
?82?????(void)deflateEnd(&strm);
?83?????return?Z_OK;
?84?}
?85?
?86?/*?Decompress?from?file?source?to?file?dest?until?stream?ends?or?EOF.
?87????inf()?returns?Z_OK?on?success,?Z_MEM_ERROR?if?memory?could?not?be
?88????allocated?for?processing,?Z_DATA_ERROR?if?the?deflate?data?is
?89????invalid?or?incomplete,?Z_VERSION_ERROR?if?the?version?of?zlib.h?and
?90????the?version?of?the?library?linked?do?not?match,?or?Z_ERRNO?if?there
?91????is?an?error?reading?or?writing?the?files.?*/
?92?int?inf(FILE?*source,?FILE?*dest)
?93?{
?94?????int?ret;
?95?????unsigned?have;
?96?????z_stream?strm;
?97?????unsigned?char?in[CHUNK];
?98?????unsigned?char?out[CHUNK];
?99?
100?????/*?allocate?inflate?state?*/
101?????strm.zalloc?=?Z_NULL;
102?????strm.zfree?=?Z_NULL;
103?????strm.opaque?=?Z_NULL;
104?????strm.avail_in?=?0;
105?????strm.next_in?=?Z_NULL;
106?????ret?=?inflateInit(&strm);
107?????if?(ret?!=?Z_OK)
108?????????return?ret;
109?
110?????/*?decompress?until?deflate?stream?ends?or?end?of?file?*/
111?????do?{
112?????????strm.avail_in?=?fread(in,?1,?CHUNK,?source);
113?????????if?(ferror(source))?{
114?????????????(void)inflateEnd(&strm);
115?????????????return?Z_ERRNO;
116?????????}
117?????????if?(strm.avail_in?==?0)
118?????????????break;
119?????????strm.next_in?=?in;
120?
121?????????/*?run?inflate()?on?input?until?output?buffer?not?full?*/
122?????????do?{
123?????????????strm.avail_out?=?CHUNK;//CHUNK=128K
124?????????????strm.next_out?=?out;
125?????????????ret?=?inflate(&strm,?Z_NO_FLUSH);
126?????????????assert(ret?!=?Z_STREAM_ERROR);??/*?state?not?clobbered?*/
127?????????????switch?(ret)?{
128?????????????case?Z_NEED_DICT:
129?????????????????ret?=?Z_DATA_ERROR;?????/*?and?fall?through?*/
130?????????????case?Z_DATA_ERROR:
131?????????????case?Z_MEM_ERROR:
132?????????????????(void)inflateEnd(&strm);
133?????????????????return?ret;
134?????????????}
135?????????????have?=?CHUNK?-?strm.avail_out;
136?????????????if?(fwrite(out,?1,?have,?dest)?!=?have?||?ferror(dest))?{
137?????????????????(void)inflateEnd(&strm);
138?????????????????return?Z_ERRNO;
139?????????????}
140?????????}?while?(strm.avail_out?==?0);
141?
142?????????/*?done?when?inflate()?says?it's?done?*/
143?????}?while?(ret?!=?Z_STREAM_END);
144?
145?????/*?clean?up?and?return?*/
146?????(void)inflateEnd(&strm);
147?????return?ret?==?Z_STREAM_END???Z_OK?:?Z_DATA_ERROR;
148?}
149?
150?/*?report?a?zlib?or?i/o?error?*/
151?void?zerr(int?ret)
152?{
153?????fputs("zpipe:?",?stderr);
154?????switch?(ret)?{
155?????case?Z_ERRNO:
156?????????if?(ferror(stdin))
157?????????????fputs("error?reading?stdin\n",?stderr);
158?????????if?(ferror(stdout))
159?????????????fputs("error?writing?stdout\n",?stderr);
160?????????break;
161?????case?Z_STREAM_ERROR:
162?????????fputs("invalid?compression?level\n",?stderr);
163?????????break;
164?????case?Z_DATA_ERROR:
165?????????fputs("invalid?or?incomplete?deflate?data\n",?stderr);
166?????????break;
167?????case?Z_MEM_ERROR:
168?????????fputs("out?of?memory\n",?stderr);
169?????????break;
170?????case?Z_VERSION_ERROR:
171?????????fputs("zlib?version?mismatch!\n",?stderr);
172?????}
173?}
174?
175?/*?compress?or?decompress?from?stdin?to?stdout?*/
176?int?main(int?argc,?char?**argv)
177?{
178?????int?ret;
179?
180?????/*?avoid?end-of-line?conversions?*/
181?????SET_BINARY_MODE(stdin);
182?????SET_BINARY_MODE(stdout);
183?
184?????/*?do?compression?if?no?arguments?*/
185?????if?(argc?==?1)?{
186?????????ret?=?def(stdin,?stdout,?Z_DEFAULT_COMPRESSION);
187?????????if?(ret?!=?Z_OK)
188?????????????zerr(ret);
189?????????return?ret;
190?????}
191?
192?????/*?do?decompression?if?-d?specified?*/
193?????else?if?(argc?==?2?&&?strcmp(argv[1],?"-d")?==?0)?{
194?????????ret?=?inf(stdin,?stdout);
195?????????if?(ret?!=?Z_OK)
196?????????????zerr(ret);
197?????????return?ret;
198?????}
199?
200?????/*?otherwise,?report?usage?*/
201?????else?{
202?????????fputs("zpipe?usage:?zpipe?[-d]?<?source?>?dest\n",?stderr);
203?????????return?1;
204?????}
205?}
接下來給出一個實例來了解一下gzip。?
Web服務器實現gzip壓縮發送
??1?#include?<string.h>
??2?#include?<stdio.h>
??3?#include?<stdlib.h>
??4?#include?<errno.h>
??5?#include?<sys/types.h>
??6?#include?<sys/socket.h>
??7?#include?<netinet/in.h>
??8?#include?<arpa/inet.h>
??9?#include?<unistd.h>
?10?#include?<signal.h>
?11?#include?<zlib.h>
?12?#include?<zconf.h>
?13?
?14?void?app_exit();
?15?int?socket_listen(u_short?port);
?16?void?send_http_head(int?clifd);
?17?void?put_long?(unsigned?char?*string,?unsigned?long?x);
?18?int?gzip_http_buffer(int?clifd,char?*msg,int?len);
?19?
?20?
?21?int?sockfd;
?22?int?main(int?argc,char?**args)
?23?{
?24?????struct?sockaddr_in?cli_sin;
?25?????socklen_t?cli_len=sizeof(cli_sin);
?26?????int?clifd;
?27?????char?buf[4096];
?28?????char?msg[4096]="<br><br><h1>Reage?Web?Server?gzip?support?text!</h1><br/><h1><a?href?=?\"http://wunaozai.cnblogs.com\">Reage?blog</a>";
?29?
?30?????signal(SIGINT,app_exit);
?31?????sockfd=socket_listen(8080);
?32?????while(1)
?33?????{
?34?????????clifd=accept(sockfd,(struct?sockaddr?*)&cli_sin,&cli_len);
?35?????????printf("連接進來的IP:%s:%u\n",inet_ntoa(cli_sin.sin_addr),ntohs(cli_sin.sin_port));
?36?????????read(clifd,buf,4096);
?37?????????printf("%s\n",buf);
?38?????????send_http_head(clifd);
?39?????????gzip_http_buffer(clifd,msg,strlen(msg));
?40?
?41?????????close(clifd);
?42?????}
?43?????close(sockfd);
?44?????return?0;
?45?}
?46?
?47?void?put_long?(unsigned?char?*string,?unsigned?long?x)//對于gzip后面的兩個字節進行位填充,這里應該是處理大端與小端
?48?{
?49?????string[0]?=?(x?&?0xff);
?50?????string[1]?=?((x?>>?8)?&?0xff)?;
?51?????string[2]?=?((x?>>?16)?&?0xff)?;
?52?????string[3]?=?((x?>>?24)?&?0xff);
?53?}
?54?/*
?55??*?對要發送的msg里面的字符進行壓縮發送
?56??*?gzip格式:?http://www.cnblogs.com/witxjp/archive/2003/12/17/1986210.html
?57??*?*/
?58?static?const?char?gzip_header[10]={0x1f,0x8b,0x08,0,0,0,0,0,0,0x03};
?59?int?gzip_http_buffer(int?clifd,char?*msg,int?len)
?60?{
?61?????z_stream?stream;
?62?????int?ret,flush;
?63?????char?in[4096];//存放輸入的數據
?64?????char?send[4096+18];//存放壓縮過后的數據
?65?????unsigned?int?have;
?66?????int?tmp;
?67?????memcpy(send,gzip_header,10);
?68?????memset(in,0,len);
?69?????stream.zalloc=Z_NULL;
?70?????stream.zfree=Z_NULL;
?71?????stream.opaque=Z_NULL;
?72?????stream.avail_in=0;
?73?????stream.next_in=Z_NULL;
?74?????memcpy(in,msg,len);
?75?????//壓縮初始化
?76?????tmp=deflateInit2(&stream,
?77?????????????Z_DEFAULT_COMPRESSION,//壓縮級別,從0-9
?78?????????????Z_DEFLATED,//壓縮方式
?79?????????????-MAX_WBITS,
?80?????????????8,
?81?????????????Z_DEFAULT_STRATEGY);
?82?????if(Z_OK!=tmp)
?83?????{
?84?????????perror("deflateInit2?Error");
?85?????????return?0;
?86?????}
?87?????stream.avail_in?=?len;?//要壓縮數據的長度
?88?????stream.next_in?=?in;????//要壓縮數據的首地址
?89?????stream.avail_out?=?4096;??//可存放的最大輸出結果的長多。就是壓縮后數據的最大長度
?90?????stream.next_out?=?send?+?10;?//存放壓縮數據的開始位置,send前十個字節用來放頭部
?91?????ret?=?deflate?(&stream,Z_FINISH);?//壓縮
?92?????switch(ret)
?93?????{
?94?????????case?Z_NEED_DICT:
?95?????????????ret=Z_DATA_ERROR;
?96?????????case?Z_DATA_ERROR:
?97?????????case?Z_MEM_ERROR:
?98?????????????(void)inflateEnd(&stream);
?99?????????????return?ret;
100?????}
101?????have?=?4096?-?stream.avail_out;
102?????unsigned?crc?=?crc32(0L,?in,?len);
103?????char?*?tail?=?send?+?10?+?have;
104?????put_long?(tail,?crc);
105?????put_long?(tail?+?4,?len);
106?????write?(clifd,?send,?have?+?18);
107?????deflateEnd?(&stream);
108?????return?1;
109?}
110?
111?void?app_exit()
112?{
113?????signal(SIGINT,SIG_DFL);
114?????close(sockfd);
115?????exit(0);
116?}
117?
118?/*
119??*?發送一個HTTP頭
120??*?*/
121?void?send_http_head(int?clifd)
122?{
123?????char?buf[4096];
124?????memset(buf,0,sizeof(buf));
125?????sprintf(buf,"HTTP/1.1?200?OK\r\n");
126?????sprintf(buf,"%sServer:wunaozai.cnblogs.com\r\n",buf);
127?????sprintf(buf,"%sContent-Encoding:?gzip\r\n",buf);//告訴瀏覽器,我接下來發送的數據是經過gzip壓縮過的
128?????sprintf(buf,"%sContent-Type:?text/html\r\n\r\n",buf);
129?????write(clifd,buf,strlen(buf));
130?}
131?
132?/*
133??*?開啟服務器監聽
134??*?port:服務器端口
135??*?成功返回套接字標識
136??*?*/
137?int?socket_listen(u_short?port)
138?{
139?????struct?sockaddr_in?sin;
140?????int?on;
141?????int?httpd=socket(PF_INET,SOCK_STREAM,0);
142?????if(httpd==-1)
143?????????perror("Fail?to?Socket");
144?????//init?sockaddr_in
145?????sin.sin_family=AF_INET;
146?????sin.sin_port=htons(port);
147?????sin.sin_addr.s_addr=htonl(INADDR_ANY);
148?????bzero(&(sin.sin_zero),8);
149?????setsockopt(httpd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
150?????if(bind(httpd,(struct?sockaddr?*)&sin,sizeof(struct?sockaddr))==-1)
151?????????perror("Fail?to?bind");
152?????//如果port指定為零那么就隨機打開一個端口
153?????if(port==0)
154?????{
155?????????socklen_t?len=sizeof(sin);
156?????????if(getsockname(httpd,(struct?sockaddr?*)&sin,&len)==-1)
157?????????????perror("Fail?to?getsockname");
158?????????port=ntohs(sin.sin_port);
159?????}
160?????if(listen(httpd,100)<0)
161?????????perror("Fail?to?listen");
162?????printf("打開端口:%u\n",port);
163?????return?httpd;
164?}
?
參考資料:?http://blog.csdn.net/reage11/article/details/8517631
:?http://www.cppblog.com/Streamlet/archive/2010/09/22/127368.aspx
:?http://blog.csdn.net/htttw/article/details/7616124
:?http://www.cppblog.com/woaidongmao/archive/2009/09/07/95495.html
:?http://blog.csdn.net/zhoudaxia/article/details/8039519
??????????????????????? :http://www.cnblogs.com/wunaozai/p/3960494.html