Linux下Socket写http协议下载文件代码以及说明

来源:互联网 发布:美国历史gdp数据统计 编辑:程序博客网 时间:2024/06/01 09:15
项目一部分需要使用socket写http协议,并下载文件,看似简单得问题,调试起来确有一些小小得问题,如果是windows平台的话,自然会简单很多,一个DownloadFile API就可以搞定,可是客户得Proj是在Linux下,不得已,从头开发了。目前得代码由于依然在win下面调试,所以移植得时候稍微注意一下就可以了。

看代码:
  1. #include <string>  
  2. #include <iostream>  
  3. #include <stdio.h>  
  4. #include <winsock.h>  
  5. #include <conio.h>  
  6.   
  7.   
  8. using namespace std;   
  9.   
  10. #pragma comment("ws2_32.lib")  
  11.   
  12. string host2ip(const string& strdomain);   
  13. void save2file(char *buffer,const string& filename);   
  14. int getlength(const string& sheader);   
  15. bool getstatus(const string& sheader);   
  16. int getleftlength(const string& sheader);   
  17. void sethttphead(const string& file,const string& server);   
  18.   
  19.   
  20. int port = 80;   
  21. int error=0;   
  22. string serveraddr;   
  23. int i = 0;   
  24. const int BUFFER_SIZE = 1024;   
  25. char buffer[BUFFER_SIZE] = {0};   
  26. char    msg[BUFFER_SIZE];   
  27. FILE *f;   
  28. const string file = "/BT/200801/3/117906.torrent";   
  29. const string url = "www.supbt.com";   
  30. const string filename = "117906.torrent";   
  31.   
  32.   
  33. int main(void)   
  34. {   
  35.         int      r;   
  36.         WSADATA  wsa;   
  37.         SOCKET   sock;   
  38.         struct   sockaddr_in sin;   
  39.         f = fopen(filename.c_str(),"ab");   
  40.         sethttphead(file,url);   
  41.         if(WSAStartup(MAKEWORD(2,2),&wsa))   
  42.         {   
  43.                 printf("WSAStartup Error: %d/n",WSAGetLastError());   
  44.                 getche();   
  45.                 return -1;   
  46.         }   
  47.   
  48.         if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)   
  49.         {   
  50.                 printf("Socket Error: %d/n",WSAGetLastError());   
  51.                 getche();   
  52.                 return -1;   
  53.         }   
  54.      
  55.         sin.sin_family=AF_INET;   
  56.         sin.sin_port=htons(port);   
  57.         serveraddr = host2ip(url);   
  58.   
  59.         cout << serveraddr << endl;   
  60.         sin.sin_addr.s_addr=inet_addr(serveraddr.c_str());   
  61.      
  62.   
  63.         if(connect(sock,(struct sockaddr *)&sin,sizeof(sin))==SOCKET_ERROR)   
  64.         {   
  65.                 printf("Connect Error: %d/n",WSAGetLastError());   
  66.                 printf("请检测网络连接!/n");   
  67.                 getche();   
  68.                 return -1;   
  69.         }   
  70.   
  71.      
  72.         if((r=send(sock,msg,sizeof(msg),0))==SOCKET_ERROR)   
  73.         {   
  74.                 printf("Send Error: %d/n",WSAGetLastError());   
  75.                 getche();   
  76.                 return -1;   
  77.         }   
  78.   
  79.         memset(buffer,0,BUFFER_SIZE);   
  80.         if((r=recv(sock,buffer,BUFFER_SIZE,0))==SOCKET_ERROR)   
  81.         {   
  82.                 printf("Recv Error: %d/n",WSAGetLastError());   
  83.                 closesocket(sock);   
  84.                 return -1;   
  85.         }   
  86.   
  87.         string header = string(buffer);   
  88.         int ilength = getlength(header);   
  89.         int leftlength = ilength;   
  90.         int icount;   
  91.         if(getstatus(header)){   
  92.                 //current is r  
  93.                 char *q = buffer;   
  94.                 char *p = strstr(buffer, "/r/n/r/n");   
  95.   
  96.                 p += 4;   
  97.                 //注意这里得 r - (p-q) 非常关键得问题  
  98.                 fwrite(p,r - (p - q),1,f);   
  99.                 leftlength -= r - (p - q);   
  100.                 int i=0;   
  101.                 icount = r - (p - q);   
  102.                 while(true)   
  103.                 {   
  104.                         memset(buffer, 0, BUFFER_SIZE);   
  105.                         r = recv(sock, buffer, BUFFER_SIZE, 0);   
  106.   
  107.                         if (r < 0) {   
  108.                                 closesocket(sock);   
  109.                                 return 2;   
  110.                         }   
  111.                         if (r == 0) {   
  112.                                 break;   
  113.                         }   
  114.                         int tmp;   
  115.                         tmp = leftlength;    //209  100 100 92  
  116.                         leftlength -= r;   
  117.                         if(leftlength > 0){   
  118.                                 fwrite(buffer,r,1,f);   
  119.                                 icount += r;   
  120.                         }   
  121.                         else if(leftlength == 0){   
  122.                                 //  
  123.                                 break;   
  124.                         }   
  125.                         else{   
  126.                                 icount += tmp;   
  127.                                 fwrite(buffer,tmp,1,f);   
  128.                                 break;   
  129.                         }   
  130.                         cout << i++ << " r is "<< r << endl;   
  131.   
  132.                 }   
  133.         }else{   
  134.                 cout << "http protocal error" << endl;   
  135.         }   
  136.         cout << icount << endl;   
  137.         fclose(f);   
  138.         closesocket(sock);   
  139.         WSACleanup();   
  140.         getche();   
  141.         return 0;   
  142. }   
  143. /* 
  144. 构造HTTP头  
  145. */  
  146. void sethttphead(const string& file,const string& server)   
  147. {   
  148.         strcat(msg,"GET ");   
  149.         strcat(msg,file.c_str());   
  150.   
  151.         strcat(msg," HTTP/1.1");   
  152.         strcat(msg,"/r/n");   
  153.   
  154.         strcat(msg,"Accept:*/*");   
  155.         strcat(msg,"/r/n");   
  156.   
  157.         //strcat(msg,"Accept-Language: zh-cn");  
  158.         //strcat(msg,"/r/n");  
  159.   
  160.         //strcat(msg,"Accept-Encoding: gzip, deflate");  
  161.         //strcat(msg,"/r/n");  
  162.   
  163.         strcat(msg,"User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");   
  164.         strcat(msg,"/r/n");   
  165.   
  166.         strcat(msg,"Host:");   
  167.         strcat(msg,server.c_str());   
  168.         strcat(msg,"/r/n");   
  169.   
  170.         strcat(msg,"Connection: Keep-Alive");   
  171.         strcat(msg,"/r/n");   
  172.         strcat(msg,"/r/n");   
  173. }   
  174. //---------------------------------------------------------------------------  
  175.   
  176. /*   
  177. 将domain 转换为IP地址   
  178. */   
  179. string host2ip(const string& strdomain)   
  180. {   
  181.         SOCKADDR_IN   saddr;   
  182.         WORD   wVersionRequested;      
  183.         WSADATA   wsaData;      
  184.         hostent   *pHostIp;   
  185.         int   nErrorNum;      
  186.         wVersionRequested   =   MAKEWORD(2,   2);      
  187.         nErrorNum   =   WSAStartup(wVersionRequested,   &wsaData);   
  188.         if(nErrorNum   !=   0)   
  189.         {   
  190.                 return   "";   
  191.         }   
  192.         saddr.sin_family   =   AF_INET;   
  193.         pHostIp   =   gethostbyname(strdomain.c_str());   
  194.         if(pHostIp   ==   NULL)   
  195.         {   
  196.                 return   "0.0.0.0";   
  197.         }   
  198.         WSACleanup();   
  199.         return   (string)inet_ntoa(*(LPIN_ADDR)*(pHostIp->h_addr_list));   
  200. }   
  201. /* 
  202. 该方法为测试用法,并为应用到项目中  
  203. */  
  204. void save2file(char *buffer,const string& filename)   
  205. {   
  206.         FILE *f;   
  207.         f = fopen(filename.c_str(),"a+");   
  208.         fwrite(buffer,strlen(buffer),1,f);   
  209.         fclose(f);   
  210. }   
  211. /* 
  212. 该方法获取待下载文件大小  
  213. */  
  214. int getlength(const string& sheader){   
  215.         char * cont_len_pos;   
  216.         unsigned long cont_length;   
  217.         const char* header = sheader.c_str();   
  218.   
  219.         cont_len_pos =(char *)strstr(header,"Content-Length:");   
  220.         cont_len_pos = (char *)strchr(cont_len_pos,' ');   
  221.         cont_len_pos++;   
  222.         sscanf(cont_len_pos, "%ld", &cont_length);   
  223.   
  224.         return cont_length;   
  225. }   
  226. /*  
  227. 该方法判断是否Get成功,不成功就取消下载文件 
  228. */  
  229. bool getstatus(const string& sheader){   
  230.         string start = "HTTP/1.1 200 OK";   
  231.         if(sheader.find(start,0) != string::npos){   
  232.                 return true;   
  233.         }   
  234.         else{   
  235.                 return false;   
  236.         }   
  237. }   
  238. /*  
  239. 该方法并没有用到,开始考虑多了 
  240. */  
  241. int getleftlength(const string& sheader){   
  242.         int nreturnl = 0;   
  243.         int ilength = sheader.length();   
  244.         string _send = "/r/n/r/n";   
  245.         int istart = sheader.find_last_of(_send);   
  246.         if(istart != string::npos){   
  247.                 nreturnl = ilength - istart -_send.length();   
  248.         }   
  249.         return nreturnl;   
  250. }   
原创粉丝点击