织梦CMS - 轻松建站从此开始!

罗索

拥有超时能力的HTTP下载

jackyhwei 发布于 2010-06-19 10:07 点击:次 
相信大家都知道WM为了节约,大量的功能都给势弃了,最混帐的就是连接,下载或者上传竟然没有超时功能,这个在客户的投诉里就混蛋了; 所以自写了一个下载,上传,代理的C++代码
TAG:

相信大家都知道WM为了节约,大量的功能都给势弃了,最混帐的就是连接,下载或者上传竟然没有超时功能,这个在客户的投诉里就混蛋了; 所以自写了一个下载,上传,代理的C++代码,当然,有人讲,何必重新写,用WINNET不就OK了吗? 问题是用系统接口,毕竟难以实现我们更理想的需求,如下载到中途,我想做一些小工作,可以暂停或者之类的!我自己写了一个完整的东西,本来是用来玩多套接字HTTP,我现在只给出一点吧,WM还不需要用得着这么复杂的功能。

老生常谈:头文件

  1. #pragma comment(lib,"note_prj.lib") 
  2.  
  3. #include <Cfgmgrapi.h> 
  4. #include <connmgr.h> 
  5. #include       <wininet.h > 
  6. #pragma comment(lib,"wininet.lib") 
  7. #pragma comment(lib, "Aygshell.lib") 
  8. #pragma comment(lib, "cellcore.lib") 

哪个有用哪个没用,我懒得整理了;

建立CHttp.h

  1. #pragma once 
  2.  
  3. #define HTTP_MAX_RECV 6000 
  4.  
  5. #define HTTP_STRING_V "GET %s HTTP/1.0\r\nHost:%s\r\nReferer:%s\r\n 
  6. Cache-Control: no-cache\r\nUser-Agent:Windows Mobile\r\n 
  7. PlatForm:Musicholic(WM)\r\nConnection: Keep-Alive\r\n\r\n" 
  8.  
  9. #define HTTP_PORT    80 
  10.  
  11. typedef struct HttpString 
  12.         char* Buffer; 
  13.         size_t Count; 
  14.         HttpString(const char* value,size_t v) 
  15.         { 
  16.                 Buffer=new char[v]; 
  17.                 memcpy(Buffer,value,v); 
  18.                 Count=v; 
  19.         } 
  20.  
  21.         ~HttpString() 
  22.         { 
  23.                 if(Buffer!=NULL) 
  24.                         delete[] Buffer; 
  25.         } 
  26.  
  27. }HTTP_STRING,*PHTTP_STRING; 
  28.  
  29. typedef struct Httpp_Status 
  30.         SOCKET Socket; 
  31.         short Count; 
  32.         BOOL Status; 
  33.         Httpp_Status() 
  34.         { 
  35.                 memset(this,0,sizeof(Httpp_Status)); 
  36.                 Socket=INVALID_SOCKET; 
  37.                 Status=TRUE; 
  38.         } 
  39.  
  40.         void CloseSocket() 
  41.         { 
  42.                 if(Socket!=INVALID_SOCKET) 
  43.                 { 
  44.                         closesocket(Socket); 
  45.                         Socket=INVALID_SOCKET; 
  46.                 } 
  47.         } 
  48.  
  49.         ~Httpp_Status() 
  50.         { 
  51.                 CloseSocket(); 
  52.         } 
  53. }HTTP_STATUS,*PHTTP_STATUS; 
  54.  
  55. class CHttp 
  56. public
  57.         CList<PHTTP_STATUS>* List; 
  58.  
  59. private
  60.  
  61.         CRITICAL_SECTION Section; 
  62. public
  63.         CHttp(void); 
  64.         ~CHttp(void); 
  65.  
  66.  
  67. public
  68.  
  69.         ///<summary> 
  70.         ///检查能否连接 
  71.         ///<summary> 
  72.         BOOL GetConnectionState(); 
  73.  
  74.         ///<summary> 
  75.         ///GPRS连接 
  76.         ///<summary> 
  77.         BOOL GPRSRasic(BOOL create); 
  78.  
  79.         ///<summary> 
  80.         ///获取下载地址的详细信息 
  81.         ///<summary> 
  82.         void getUrlMessage(const char* url,char* host,
  83. char* httpbuf,short* port); 
  84.  
  85.         ///<summary> 
  86.         ///文件下载(用free()去释放内存) 
  87.         ///<summary> 
  88.         char* Download(const char* url); 
  89.  
  90.  
  91.         ///<summary> 
  92.         ///线程 
  93.         ///<summary> 
  94.         static DWORD CALLBACK Run(LPVOID lpVoid); 
  95. }; 

建立CHttp.CPP

  1. CHttp::CHttp(void
  2.         ::InitializeCriticalSection(&Section); 
  3.  
  4.         WSADATA* wsaData=new WSADATA; 
  5.         WSAStartup(MAKEWORD(1,1),wsaData); 
  6.         delete wsaData; 
  7.  
  8.         List=new CList<PHTTP_STATUS>(); 
  9.  
  10.         HANDLE thread=CreateThread(NULL,0,Run,this,0,0); 
  11.         CloseHandle(thread); 
  12.  
  13. CHttp::~CHttp(void
  14.  
  15.  
  16. DWORD CALLBACK CHttp::Run(LPVOID lpVoid) 
  17.         CHttp* object=(CHttp*)lpVoid; 
  18.         CList<PHTTP_STATUS>* List=object->List; 
  19.  
  20.         int index=0; 
  21.         POSITION pos=NULL; 
  22.  
  23.         Sleep(1500); 
  24.         while(TRUE) 
  25.         { 
  26.                 index=0; 
  27.                 pos=NULL; 
  28.                 while(index<List->GetCount()) 
  29.                 { 
  30.                         pos=List->FindIndex( index ); 
  31.                         PHTTP_STATUS obj=List->GetAt( pos ); 
  32.                         if(!obj->Status || obj->Count>10) 
  33.                         { 
  34.                                 Sleep(500); 
  35.                                 delete obj; 
  36.                                 List->RemoveAt(pos); 
  37.                         } 
  38.                         else 
  39.                         { 
  40.                                 obj->Count++; 
  41.                                 index++; 
  42.                         } 
  43.                 } 
  44.                 ::Sleep(3000); 
  45.         } 
  46.  
  47.   
  48.  
  49. BOOL CHttp::GetConnectionState() 
  50.         int index=0; 
  51.         BOOL create=FALSE; 
  52.  
  53.         SOCKADDR_IN* addr=new SOCKADDR_IN; 
  54.  
  55.         while(index<2)//首先检测网络状态 
  56.         { 
  57. addr->sin_family=AF_INET; 
  58. addr->sin_port=htons(80); 
  59. addr->sin_addr.s_addr = inet_addr ("64.233.189.104");
  60. //这是google的地址 
  61.                 
  62. PHTTP_STATUS sockStatus=new HTTP_STATUS; 
  63. sockStatus->Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  64. //建立套接字 连接套接字 
  65. List->AddTail(sockStatus); 
  66. if( connect(sockStatus->Socket,(SOCKADDR*)addr,sizeof(SOCKADDR_IN))
  67. !=SOCKET_ERROR ) 
  68. sockStatus->Status=FALSE; 
  69. delete addr; 
  70. return TRUE; 
  71. sockStatus->Status=FALSE; 
  72.                 
  73. if(!create) 
  74. ::EnterCriticalSection(&Section); 
  75. create=GPRSRasic(create); 
  76. ::LeaveCriticalSection(&Section); 
  77. if(create) 
  78. Sleep(3000); 
  79. WSADATA* wsaData=new WSADATA; 
  80. WSAStartup(MAKEWORD(1,1),wsaData); 
  81. delete wsaData; 
  82. index++; 
  83. delete addr; 
  84.  
  85. return FALSE; 
  86.  
  87.  
  88. BOOL CHttp::GPRSRasic(BOOL create) 
  89.         if(create) return TRUE; 
  90.         HANDLE m_hConnMgr=NULL; 
  91.         m_hConnMgr = ConnMgrApiReadyEvent(); 
  92.         if (!m_hConnMgr) 
  93.                 return FALSE; 
  94.         DWORD dwResult = WaitForSingleObject(m_hConnMgr, 3000); 
  95.         // 关闭 
  96.         if (m_hConnMgr) 
  97.         { 
  98.                 CloseHandle(m_hConnMgr); 
  99.                 m_hConnMgr = NULL; 
  100.         } 
  101.         if (dwResult != WAIT_OBJECT_0)    //找到了,GPRS可以用 
  102.         { 
  103.                 return TRUE; 
  104.         } 
  105.  
  106.         DWORD dwTimeout = 15000;
  107. // 连接超时时间 
  108.         BOOL bEstaCon = TRUE; 
  109.         // 获得网络的GUID值 
  110.         GUID guidNetworkObject; 
  111.         DWORD dwIndex = 0; 
  112.  
  113. if (ConnMgrMapURL(L"http://www.google.com", &guidNetworkObject, &dwIndex)
  114.  == E_FAIL) 
  115. bEstaCon = TRUE; 
  116. if(bEstaCon) 
  117. // 建立连接 
  118. CONNMGR_CONNECTIONINFO* ccInfo=new CONNMGR_CONNECTIONINFO; 
  119. memset(ccInfo, 0, sizeof(CONNMGR_CONNECTIONINFO)); 
  120. ccInfo->cbSize = sizeof(CONNMGR_CONNECTIONINFO); 
  121. ccInfo->dwParams = CONNMGR_PARAM_GUIDDESTNET; 
  122. ccInfo->dwFlags = CONNMGR_FLAG_PROXY_HTTP;
  123. //HTTP的也可以加入WAP等 
  124. ccInfo->dwPriority = CONNMGR_PRIORITY_USERINTERACTIVE; 
  125. ccInfo->bExclusive = FALSE; 
  126. ccInfo->guidDestNet = guidNetworkObject;//网络地址映射的GUID
  127. //开始连接
  128. DWORD dwStatus=0;
  129. if (ConnMgrEstablishConnectionSync
  130. (ccInfo, &m_hConnMgr,dwTimeout,&dwStatus) != E_FAIL)
  131. bEstaCon=TRUE;
  132. else
  133. bEstaCon=FALSE;
  134. delete ccInfo;
  135. }
  136. if(m_hConnMgr != NULL)
  137. ConnMgrReleaseConnection(m_hConnMgr, TRUE);
  138. // 第2个参数决定是否缓存连接,默认缓存连接时间为60秒        
  139. Sleep(15000); 
  140. return TRUE; 
  141.  
  142. void CHttp::getUrlMessage(const char* url,
  143. char* host,char* httpbuf,short* port) 
  144.         char* tmpUrl=new char[strlen(url)+1]; 
  145.         strcpy(tmpUrl,url); 
  146.         char* purl=tmpUrl; 
  147.         purl+=7;          //除去http:// 
  148.         char* tpHost=purl; 
  149.         while(*purl && *purl++!=0x2f){} //0x2f ==/ 
  150.         purl--; 
  151.         *purl=0; 
  152.         strcpy(host,tpHost); 
  153.  
  154.         *purl=0x2f; 
  155.  
  156.         if(httpbuf!=NULL) 
  157.         { 
  158.                 char* pRefener=tmpUrl+strlen(url)-1; 
  159.                 while(*pRefener!=0x2f){pRefener--;} 
  160.                 pRefener++; 
  161.                 *pRefener=0; 
  162.                 pRefener=NULL; 
  163.                 sprintf(httpbuf,HTTP_STRING_V,url,host,tmpUrl); 
  164.                 delete[] tmpUrl; 
  165.         } 
  166.         tpHost=host; 
  167.         tpHost=strstr(host,":"); 
  168.         if(tpHost!=NULL) 
  169.         { 
  170.                 *tpHost=NULL; 
  171.                 *tpHost++; 
  172.                 *port=atoi(tpHost); 
  173.         }
  174. }
  175.  
  176. char* CHttp::Download(const char* url) 
  177.         if(url==NULL || strlen(url)<10)return NULL; 
  178.  
  179.         if(!GetConnectionState() )return NULL;//先判断下网络状态 
  180.  
  181.         char* host=new char[50]; 
  182.         char* httpbuf=new char[700]; 
  183.         short port=HTTP_PORT; 
  184.         memset(host,0,50); 
  185.         memset(httpbuf,0,700); 
  186.  
  187.         getUrlMessage(url,host,httpbuf,&port); 
  188.         
  189.         DWORD dwIPAddr=inet_addr(host); 
  190.         hostent* phostent=NULL; 
  191.         if(dwIPAddr==INADDR_NONE) 
  192.                 phostent=gethostbyname(host); 
  193.  
  194.         delete[] host; 
  195.         
  196.         //如果主机解析错误或者连接不到服务器,则返回false 
  197.         if (phostent==NULL && dwIPAddr==INADDR_NONE) 
  198.         { 
  199.                 delete[] httpbuf; 
  200.                 return NULL; 
  201.         } 
  202.  
  203.         SOCKADDR_IN addr; 
  204.         addr.sin_family=AF_INET; 
  205.         addr.sin_port=htons(port); 
  206.         if(dwIPAddr==INADDR_NONE) 
  207. memmove(&addr.sin_addr,phostent->h_addr_list[0],
  208. sizeof(phostent->h_addr_list[0])); 
  209.         else 
  210. addr.sin_addr.S_un.S_addr=dwIPAddr;
  211.  
  212.         PHTTP_STATUS sockStatus=new HTTP_STATUS; 
  213.         sockStatus->Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  214. //建立套接字 连接套接字 
  215.  
  216.         List->AddTail(sockStatus);//不用多讲,放入列表 
  217.  
  218.         if (sockStatus->Socket==INVALID_SOCKET
  219.  || connect(sockStatus->Socket,(SOCKADDR*)&addr,sizeof(addr))==SOCKET_ERROR
  220.  || !sockStatus->Status) 
  221.         { 
  222.                 sockStatus->Status=FALSE; 
  223.                 delete[] httpbuf; 
  224.                 return NULL; 
  225.         } 
  226.  
  227.         sockStatus->Count=0; 
  228.  
  229.         //发送头标识 
  230.         int sen=send(sockStatus->Socket,httpbuf,strlen(httpbuf)+1,0); 
  231.  
  232.         delete[] httpbuf; 
  233.  
  234.         char* rcvbuf=new char[HTTP_MAX_RECV]; 
  235.         int nRcv=recv(sockStatus->Socket,rcvbuf,HTTP_MAX_RECV,0); 
  236.         if (nRcv < 100 || !sockStatus->Status) 
  237.         { 
  238.                 delete[] rcvbuf; 
  239.                 return false
  240.         } 
  241.  
  242.         sockStatus->Count=0; 
  243.         //去掉返回的头标识 
  244.         char* p=rcvbuf+20; 
  245.         int startChar=20; 
  246.         int removeInt=1; 
  247.         while(*p++) 
  248.         { 
  249.           startChar++; 
  250.           if (*(p-3)=='\r' && *(p-2)=='\n' && *(p-1)=='\r' && *p=='\n'
  251.           { 
  252.             p++; 
  253.             break
  254.           } 
  255.         }
  256.  
  257.         CList<PHTTP_STRING>* string=new CList<PHTTP_STRING>();
  258.         string->AddTail( new HTTP_STRING(p,nRcv-startChar-removeInt));
  259.         size_t litCount=nRcv-startChar-removeInt; 
  260.  
  261.         //写入接收到的字节 
  262.         while(sockStatus->Status) 
  263.         { 
  264.                 memset(rcvbuf,0,HTTP_MAX_RECV); 
  265.                 nRcv=recv(sockStatus->Socket,rcvbuf,HTTP_MAX_RECV,0); 
  266.                 sockStatus->Count=0; 
  267.  
  268.                 if (nRcv<1)break
  269.  
  270.                 litCount+=nRcv; 
  271.                 string->AddTail( new HTTP_STRING(rcvbuf,nRcv) ); 
  272.         } 
  273.         delete[] rcvbuf; 
  274.         
  275.         char* Buffer =(char*)malloc(sizeof(char) * litCount); 
  276.         p=Buffer; 
  277.         for(POSITION pos=string->GetHeadPosition();pos!=NULL;string->GetNext(pos)) 
  278.         { 
  279.                 PHTTP_STRING obj=string->GetAt(pos); 
  280.                 memcpy(p,obj->Buffer,obj->Count); 
  281.                 p+=obj->Count; 
  282.                 delete obj; 
  283.         } 
  284.         string->RemoveAll(); 
  285.         delete string; 
  286.         sockStatus->Status=FALSE; 
  287.  
  288.         return Buffer; 

使用:

  1. CHttp http; 
  2. char* buffer=http.Download("http://www.rosoo.net/"); 
  3. free(buffer); 

内存方面我尽量做到自我释放,我发现玩WM的C++,对内存的使用真的要十分小心

(yanql)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201006/9668.html]
本文出处:yanql.blog.51cto.com 作者:yanql
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
相关文章
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容