大家都很熟悉HTTP协议的应用,因为每天都在网络上浏览着不少东西,也都知道是HTTP协议是相当简单的。每次用thunder之类的下载软件下载网页,当用到那个“用thunder下载全部链接”时总觉得很神奇。后来想想,其实要实现这些下载功能也并不难,只要按照HTTP协议发送request,然后对接收到的数据进行分析,如果页面上还有href之类的链接指向标志就可以进行深一层的下载了。HTTP协议目前用的最多的是1.1版本,要全面透彻地搞懂它就参考RFC2616文档吧。我是怕rfc文档了的,要看自己去看吧^_^源代码如下:/*******http客户端程序httpclient.c************/#includestdio.h#includestdlib.h#includestring.h#includesys/types.h#includesys/socket.h#includeerrno.h#includeunistd.h#includenetinet/in.h#includelimits.h#includenetdb.h#includearpa/inet.h#includectype.h//////////////////////////////httpclient.c开始////////////////////////////////////////////********************************************功能:搜索字符串右边起的第一个匹配字符********************************************/char*Rstrchr(char*s,charx){inti=strlen(s);if(!(*s))return0;while(s[i-1])if(strchr(s+(i-1),x))return(s+(i-1));elsei--;return0;}/********************************************功能:把字符串转换为全小写********************************************/voidToLowerCase(char*s){while(s&&*s){*s=tolower(*s);s++;}}/**************************************************************功能:从字符串src中分析出网站地址和端口,并得到用户要下载的文件***************************************************************/voidGetHost(char*src,char*web,char*file,int*port){char*pA;char*pB;memset(web,0,sizeof(web));memset(file,0,sizeof(file));*port=0;if(!(*src))return;pA=src;if(!strncmp(pA,http://,strlen(http://)))pA=src+strlen(http://);elseif(!strncmp(pA,https://,strlen(https://)))pA=src+strlen(https://);pB=strchr(pA,'/');if(pB){memcpy(web,pA,strlen(pA)-strlen(pB));if(pB+1){memcpy(file,pB+1,strlen(pB)-1);file[strlen(pB)-1]=0;}}elsememcpy(web,pA,strlen(pA));if(pB)web[strlen(pA)-strlen(pB)]=0;elseweb[strlen(pA)]=0;pA=strchr(web,':');if(pA)*port=atoi(pA+1);else*port=80;}intmain(intargc,char*argv[]){intsockfd;charbuffer[1024];structsockaddr_inserver_addr;structhostent*host;intportnumber,nbytes;charhost_addr[256];charhost_file[1024];charlocal_file[256];FILE*fp;charrequest[1024];intsend,totalsend;inti;char*pt;if(argc!=2){fprintf(stderr,Usage:%sweb-address/a/n,argv[0]);exit(1);}printf(parameter.1is:%s/n,argv[1]);ToLowerCase(argv[1]);/*将参数转换为全小写*/printf(lowercaseparameter.1is:%s/n,argv[1]);GetHost(argv[1],host_addr,host_file,&portnumber);/*分析网址、端口、文件名等*/printf(webhost:%s/n,host_addr);printf(hostfile:%s/n,host_file);printf(portnumber:%d/n/n,portnumber);if((host=gethostbyname(host_addr))==NULL)/*取得主机IP地址*/{fprintf(stderr,Gethostnameerror,%s/n,strerror(errno));exit(1);}/*客户程序开始建立sockfd描述符*/if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)/*建立SOCKET连接*/{fprintf(stderr,SocketError:%s/a/n,strerror(errno));exit(1);}/*客户程序填充服务端的资料*/bzero(&server_addr,sizeof(server_addr));server_addr.sin_family=AF_INET;server_addr.sin_port=htons(portnumber);server_addr.sin_addr=*((structin_addr*)host-h_addr);/*客户程序发起连接请求*/if(connect(sockfd,(structsockaddr*)(&server_addr),sizeof(structsockaddr))==-1)/*连接网站*/{fprintf(stderr,ConnectError:%s/a/n,strerror(errno));exit(1);}sprintf(request,GET/%sHTTP/1.1/r/nAccept:*/*/r/nAccept-Language:zh-cn/r/n/User-Agent:Mozilla/4.0(compatible;MSIE5.01;WindowsNT5.0)/r/n/Host:%s:%d/r/nConnection:Close/r/n/r/n,host_file,host_addr,portnumber);printf(%s,request);/*准备request,将要发送给主机*//*取得真实的文件名*/if(host_file&&*host_file)pt=Rstrchr(host_file,'/');elsept=0;memset(local_file,0,sizeof(local_file));if(pt&&*pt){if((pt+1)&&*(pt+1))strcpy(local_file,pt+1);elsememcpy(local_file,host_file,strlen(host_file)-1);}elseif(host_file&&*host_file)strcpy(local_file,host_file);elsestrcpy(local_file,index.html);printf(localfilenametowrite:%s/n/n,local_file);/*发送http请求request*/send=0;totalsend=0;nbytes=strlen(request);while(totalsendnbytes){send=write(sockfd,request+totalsend,nbytes-totalsend);if(send==-1){printf(senderror!%s/n,strerror(errno));exit(0);}totalsend+=send;printf(%dbytessendOK!/n,totalsend);}fp=fopen(local_file,a);if(!fp){printf(createfileerror!%s/n,strerror(errno));return0;}printf(/nThefollowingistheresponseheader:/n);i=0;/*连接成功了,接收http响应,response*/while((nbytes=read(sockfd,buffer,1))==1){if(i4){if(buffer[0]=='/r'||buffer[0]=='/n')i++;elsei=0;printf(%c,buffer[0]);/*把http头信息打印在屏幕上*/}else{fwrite(buffer,1,1,fp);/*将http主体信息写入文件*/i++;if(i%1024==0)fflush(fp);/*每1K时存盘一次*/}}fclose(fp);/*结束通讯*/close(sockfd);exit(0);}zj@zj:~/C_pram/practice/http_client$lshttpclienthttpclient.czj@zj:~/C_pram/practice/http_client$./httpclient::::80GET/HTTP/1.1Accept:*/*Accept-Language:zh-cnUser-Agent:Mozilla/4.0(compatible;MSIE5.01;WindowsNT5.0)Host::Closelocalfilenametowrite:index.html163bytessendOK!Thefollowingistheresponseheader:HTTP/1.1200OKDate:Wed,29Oct200810:41:40GMTServer:BWS/1.0Content-Length:4216Content-Type:text/htmlCache-Control:privateExpires:Wed,29Oct200810:41:40GMTSet-Cookie:BAIDUID=A93059C8DDF7F1BC47C10CAF9779030E:FG=1;expires=Wed,29-Oct-3810:41:40GMT;path=/;domain=.baidu.comP3P:CP=OTIDSPCORIVAOURINDCOMzj@zj:~/C_pram/practice/http_client$lshttpclie