HTTP协议的C语言编程实现实例

转载地址:http://zhoulifa.bokee.com/4647374.html

大家都很熟悉HTTP协议的应用,因为每天都在网络上浏览着不少东西,也都知道是HTTP协议是相当简单的。每次用到FlashGet之类的下载软件下载网页,当用到那个“用FlashGet下载全部链接”时总觉得很神奇。

后来想想,其实要实现这些下载功能也并不难,只要按照HTTP协议发送request,然后对接收到的数据进行分析,如果页面上还有href之类的链接指向标志就可以进行深一层的下载了。HTTP协议目前用的最多的是1.1版本,要全面透彻地搞懂它就参考RFC2616文档吧。

下面是我用C语言编程写的一个http下载程序,希望对大家有些启发。源代码如下:


  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. #include <string.h>   
  4. #include <sys/types.h>   
  5. #include <sys/socket.h>   
  6. #include <errno.h>   
  7. #include <unistd.h>   
  8. #include <netinet/in.h>   
  9. #include <limits.h>   
  10. #include <netdb.h>   
  11. #include <arpa/inet.h>   
  12. #include <ctype.h>   
  13.   
  14. //httpclient.c 开始///   
  15.   
  16. /******************************************** 
  17. 功能:搜索字符串右边起的第一个匹配字符 
  18. ********************************************/  
  19. char * Rstrchr(char * s, char x)  {  
  20.   int i = strlen(s);  
  21.   if(!(*s))  return 0;  
  22.   while(s[i-1]) if(strchr(s + (i - 1), x))  return (s + (i - 1));  else i--;  
  23.   return 0;  
  24. }  
  25.   
  26. /******************************************** 
  27. 功能:把字符串转换为全小写 
  28. ********************************************/  
  29. void ToLowerCase(char * s)  {  
  30.   while(*s)  *s=tolower(*s++);  
  31. }  
  32.   
  33. /************************************************************** 
  34. 功能:从字符串src中分析出网站地址和端口,并得到用户要下载的文件 
  35. ***************************************************************/  
  36. void GetHost(char * src, char * web, char * file, int * port)  {  
  37.   char * pA;  
  38.   char * pB;  
  39.   memset(web, 0, sizeof(web));  
  40.   memset(file, 0, sizeof(file));  
  41.   *port = 0;  
  42.   if(!(*src))  return;  
  43.   pA = src;  
  44.   if(!strncmp(pA, "http://", strlen("http://")))  pA = src+strlen("http://");  
  45.   else if(!strncmp(pA, "https://", strlen("https://")))  pA = src+strlen("https://");  
  46.   pB = strchr(pA, '/');  
  47.   if(pB)  {  
  48.     memcpy(web, pA, strlen(pA) - strlen(pB));  
  49.     if(pB+1)  {  
  50.       memcpy(file, pB + 1, strlen(pB) - 1);  
  51.       file[strlen(pB) - 1] = 0;  
  52.     }  
  53.   }  
  54.   else  memcpy(web, pA, strlen(pA));  
  55.   if(pB)  web[strlen(pA) - strlen(pB)] = 0;  
  56.   else  web[strlen(pA)] = 0;  
  57.   pA = strchr(web, ':');  
  58.   if(pA)  *port = atoi(pA + 1);  
  59.   else *port = 80;  
  60. }  
  61.   
  62. /********************************************************************* 
  63. *filename: httpclient.c 
  64. *purpose: HTTP协议客户端程序,可以用来下载网页 
  65. *wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com) 
  66.            Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言 
  67. *date time:2006-03-11 21:49:00 
  68. *Note: 任何人可以任意复制代码并运用这些代码,当然包括你的商业用途 
  69. *                         但请遵循GPL 
  70. *********************************************************************/  
  71. int main(int argc, char *argv[])  
  72. {  
  73.   int sockfd;  
  74.   char buffer[1024];  
  75.   struct sockaddr_in server_addr;  
  76.   struct hostent *host;  
  77.   int portnumber,nbytes;  
  78.   char host_addr[256];  
  79.   char host_file[1024];  
  80.   char local_file[256];  
  81.   FILE * fp;  
  82.   char request[1024];  
  83.   int send, totalsend;  
  84.   int i;  
  85.   char * pt;  
  86.   
  87.   if(argc!=2)  
  88.   {  
  89.     fprintf(stderr,"Usage:%s web-address\a\n",argv[0]);  
  90.     exit(1);  
  91.   }  
  92.   printf("parameter.1 is: %s\n", argv[1]);  
  93.   ToLowerCase(argv[1]);/*将参数转换为全小写*/  
  94.   printf("lowercase parameter.1 is: %s\n", argv[1]);  
  95.   
  96.   GetHost(argv[1], host_addr, host_file, &portnumber);/*分析网址、端口、文件名等*/  
  97.   printf("webhost:%s\n", host_addr);  
  98.   printf("hostfile:%s\n", host_file);  
  99.   printf("portnumber:%d\n\n", portnumber);  
  100.   
  101.   if((host=gethostbyname(host_addr))==NULL)/*取得主机IP地址*/  
  102.   {  
  103.     fprintf(stderr,"Gethostname error, %s\n", strerror(errno));  
  104.     exit(1);  
  105.   }  
  106.   
  107.   /* 客户程序开始建立 sockfd描述符 */  
  108.   if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)/*建立SOCKET连接*/  
  109.   {  
  110.     fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));  
  111.     exit(1);  
  112.   }  
  113.   
  114.   /* 客户程序填充服务端的资料 */  
  115.   bzero(&server_addr,sizeof(server_addr));  
  116.   server_addr.sin_family=AF_INET;  
  117.   server_addr.sin_port=htons(portnumber);  
  118.   server_addr.sin_addr=*((struct in_addr *)host->h_addr);  
  119.   
  120.   /* 客户程序发起连接请求 */  
  121.   if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)/*连接网站*/  
  122.   {  
  123.     fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));  
  124.     exit(1);  
  125.   }  
  126.   
  127.   sprintf(request, "GET /%s HTTP/1.1\r\nAccept: */*\r\nAccept-Language: zh-cn\r\n\ 
  128. User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)\r\n\ 
  129. Host: %s:%d\r\nConnection: Close\r\n\r\n", host_file, host_addr, portnumber); 
  130.   printf("%s", request);/*准备request,将要发送给主机*/  
  131.   
  132.   /*取得真实的文件名*/  
  133.   if(host_file && *host_file)  pt = Rstrchr(host_file, '/');  
  134.   else pt = 0;  
  135.   
  136.   memset(local_file, 0, sizeof(local_file));  
  137.   if(pt && *pt)  {  
  138.     if((pt + 1) && *(pt+1))  strcpy(local_file, pt + 1);  
  139.     else  memcpy(local_file, host_file, strlen(host_file) - 1);  
  140.   }  
  141.   else if(host_file && *host_file)  strcpy(local_file, host_file);  
  142.   else  strcpy(local_file, "index.html");  
  143.   printf("local filename to write:%s\n\n", local_file);  
  144.   
  145.   /*发送http请求request*/  
  146.   send = 0;totalsend = 0;  
  147.   nbytes=strlen(request);  
  148.   while(totalsend < nbytes) {  
  149.     send = write(sockfd, request + totalsend, nbytes - totalsend);  
  150.     if(send==-1)  {printf("send error!%s\n", strerror(errno));exit(0);}  
  151.     totalsend+=send;  
  152.     printf("%d bytes send OK!\n", totalsend);  
  153.   }  
  154.   
  155.   fp = fopen(local_file, "a");  
  156.   if(!fp)  {  
  157.     printf("create file error! %s\n", strerror(errno));  
  158.     return 0;  
  159.   }  
  160.   printf("\nThe following is the response header:\n");  
  161.   i=0;  
  162.   /* 连接成功了,接收http响应,response */  
  163.   while((nbytes=read(sockfd,buffer,1))==1)  
  164.   {  
  165.     if(i < 4)  {  
  166.       if(buffer[0] == '\r' || buffer[0] == '\n')  i++;  
  167.       else i = 0;  
  168.       printf("%c", buffer[0]);/*把http头信息打印在屏幕上*/  
  169.     }  
  170.     else  {  
  171.       fwrite(buffer, 1, 1, fp);/*将http主体信息写入文件*/  
  172.       i++;  
  173.       if(i%1024 == 0)  fflush(fp);/*每1K时存盘一次*/  
  174.     }  
  175.   }  
  176.   fclose(fp);  
  177.   /* 结束通讯 */  
  178.   close(sockfd);  
  179.   exit(0);  
  180. }  
  181. //httpclient.c 结束///  
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值