HttpRequest.cpp
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:17k
源码类别:

P2P编程

开发平台:

Visual C++

  1. /*
  2.  *  Openmysee
  3.  *
  4.  *  This program is free software; you can redistribute it and/or modify
  5.  *  it under the terms of the GNU General Public License as published by
  6.  *  the Free Software Foundation; either version 2 of the License, or
  7.  *  (at your option) any later version.
  8.  *
  9.  *  This program is distributed in the hope that it will be useful,
  10.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *  GNU General Public License for more details.
  13.  *
  14.  *  You should have received a copy of the GNU General Public License
  15.  *  along with this program; if not, write to the Free Software
  16.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17.  *
  18.  */
  19. // HttpDownload.cpp: implementation of the HttpDownload class.
  20. //
  21. //////////////////////////////////////////////////////////////////////
  22. #include "stdafx.h"
  23. #include <LIMITS.H>
  24. #include <TCHAR.H>
  25. #include "HttpRequest.h"
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #ifdef _MYDEBUG
  29. #undef THIS_FILE
  30. static TCHAR THIS_FILE[]=__FILE__;
  31. #define new DEBUG_NEW
  32. #endif
  33. //////////////////////////////////////////////////////////////////////
  34. // Construction/Destruction
  35. //////////////////////////////////////////////////////////////////////
  36. BOOL  HttpRequest::GetCookieEx(LPCTSTR lpszUrlName, LPCTSTR lpszCookieDataName, LPTSTR lpszCookieData, LPDWORD lpdwSize)
  37. {
  38.     DWORD   len = 0;
  39.     InternetGetCookie(lpszUrlName, NULL, NULL, &len);
  40.     if(len == 0)
  41.     {
  42.         return FALSE;   //no cookie exist
  43.     }
  44.     len += 10;
  45.     LPTSTR   bufcookiedata = new TCHAR[len];
  46.     memset(bufcookiedata, 0, sizeof(TCHAR)*len);
  47.     if(InternetGetCookie(lpszUrlName, NULL, bufcookiedata, &len) != TRUE)
  48.     {
  49.         delete[] bufcookiedata;
  50.         return FALSE;
  51.     }
  52.     bool    parseOK = false;
  53.     while(1)
  54.     {    
  55.         LPTSTR datastart = _tcsstr(bufcookiedata, lpszCookieDataName);
  56.         if(datastart == NULL)
  57.             return FALSE;
  58.         LPTSTR indexspace = NULL;
  59.         LPTSTR indexequal = NULL;
  60.         indexequal = _tcschr(datastart, _T('='));
  61.         if(indexequal == NULL)
  62.             break;
  63.         indexequal++;
  64.         indexspace = _tcschr(datastart, _T(';'));
  65.         if(indexspace == NULL)  //这是最后一个data
  66.             indexspace = _tcschr(datastart, 0);
  67.         assert(indexspace > indexequal);
  68.         DWORD m_actuallen = indexspace - indexequal + 1;    //len + null terminnal
  69.         assert(lpdwSize != NULL);
  70.         if(lpszCookieData == NULL || *lpdwSize < m_actuallen)
  71.         {
  72.             *lpdwSize = m_actuallen;
  73.         }
  74.         else
  75.         {
  76.             memset(lpszCookieData, 0, sizeof(TCHAR)*(*lpdwSize));
  77.             _tcsncpy(lpszCookieData, indexequal, indexspace - indexequal);
  78.         }
  79.         parseOK = true;
  80.         break;
  81.     }
  82.     delete[] bufcookiedata;
  83.     if(!parseOK)
  84.     {
  85.         return FALSE;
  86.     }
  87.     else
  88.         return TRUE;
  89. }
  90. //HTTP信标
  91. #define HTTP_REQUEST_LIMIT_NAME _T("_GAOV_HTTP_REQUEST_LIMIT")
  92. static HANDLE m_hSemaphore = CreateSemaphore(NULL, 5, 5, HTTP_REQUEST_LIMIT_NAME);
  93. int HttpRequest::b_useproxy = 0;
  94. TCHAR HttpRequest::m_proxystr[256] = _T("");
  95. #define INTERNET_CONNECT_ADAGENT _T("Mysee_Client")
  96. void HttpRequest::SetProxyName(LPCWSTR s)
  97. {
  98. #ifdef _UNICODE
  99. wcscpy(m_proxystr, s);
  100. #else
  101. char* m_innerbufferA = new char[1024];
  102. WideCharToMultiByte(CP_ACP, 0, s, -1, m_innerbufferA, 1024, NULL, NULL);
  103. strcpy(m_proxystr, m_innerbufferA);
  104. delete[] m_innerbufferA;
  105. #endif
  106. }
  107. void HttpRequest::SetProxyName(LPCSTR s)
  108. {
  109. #ifdef _UNICODE
  110. WCHAR* m_innerbufferW = new WCHAR[1024];
  111. MultiByteToWideChar(CP_ACP, 0, s, -1, m_innerbufferW, 1024);
  112. wcscpy(m_proxystr, m_innerbufferW);
  113. delete[] m_innerbufferW;
  114. #else
  115. strcpy(m_proxystr, s);
  116. #endif
  117. }
  118. HttpRequest::HttpRequest()
  119. {
  120. Connect_timeout = 60000;
  121. Request_timeout = 120000;
  122. recvBuf = NULL;
  123. // HSO = NULL;
  124. m_hInternet = NULL;
  125. errorcode = 0;
  126. // InitializeCriticalSection(&m_hSync);
  127. for(int j = 0; j<EVENT_SERIES; j++)
  128. m_hEvent[j] = CreateEvent(NULL, TRUE, FALSE, NULL);
  129. ResetEvent(m_hEvent[0]);
  130. fWide = FALSE;
  131. }
  132. BOOL HttpRequest::Create(UINT cto, UINT rto, BOOL wide)
  133. {
  134. // b_userStop = FALSE;
  135. fWide = wide;
  136. h_File = NULL;
  137. Connect_timeout = cto;
  138. Request_timeout = rto;
  139. errorcode = 0;
  140. m_dwOffset = m_dwOffsetEnd = UINT_MAX;
  141. // DWORD wtmp;
  142. // ResetEvent(m_hEvent[0]);
  143. // ::CreateThread(NULL, 0, InitialCallback, this, 0, &wtmp);
  144. // WaitForSingleObject(m_hEvent[0], INFINITE);
  145. // if(errorcode != 0)return FALSE;
  146. return TRUE;
  147. }
  148. HttpRequest::~HttpRequest()
  149. {
  150. for(int j = 0; j<EVENT_SERIES;j++)
  151. CloseHandle(m_hEvent[j]);
  152. // DeleteCriticalSection(&m_hSync);
  153. if(recvBuf)delete[] recvBuf;
  154. }
  155. void HttpRequest::SetStopRequest()
  156. {
  157. SetEvent(m_hEvent[0]);
  158. }
  159. void HttpRequest::ResumeStopRequest()
  160. {
  161. ResetEvent(m_hEvent[0]);
  162. }
  163. UINT HttpRequest::WaitingEvent(DWORD timeout)
  164. {
  165. if((errorcode = GetLastError()) != ERROR_IO_PENDING)
  166. {
  167. return 1;
  168. }
  169. DWORD result = WaitForMultipleObjects(EVENT_SERIES, m_hEvent, 
  170. FALSE, timeout);
  171. switch(result)
  172. {
  173. case WAIT_OBJECT_0: //外部中止
  174. errorcode = USER_STOP;
  175. return 1;
  176. case WAIT_OBJECT_0 + 1: //内部中止
  177. if(errorcode)
  178. return 1;
  179. else
  180. return 0;
  181. case WAIT_TIMEOUT: //连接超时
  182. errorcode = 32808;
  183. return 1;
  184. case WAIT_FAILED: //严重错误
  185. errorcode = ERROR_STOP;
  186. return 1;
  187. }
  188. return 1;
  189. }
  190. void HttpRequest::HDResetEvent()
  191. {
  192. for(int i = 1; i< EVENT_SERIES; i++)
  193. ResetEvent(m_hEvent[i]); 
  194. }
  195. int  HttpRequest::ReadStringEx()
  196. {
  197. if(recvBuf == NULL)return -1;
  198. if(readstrpos >= buflength)return -1;
  199. int oldpos = -1;
  200. if(fWide)
  201. {
  202. WCHAR* head = (WCHAR*) recvBuf;
  203. for(UINT i = readstrpos; (i*sizeof(WCHAR))<buflength; i++)
  204. {
  205. if(*(head + i) == L'n')break;
  206. }
  207. oldpos = readstrpos;
  208. readstrpos = i+1;
  209. if(i != readstrpos && *(head + i - 1) == L'r')
  210. *(head + i - 1) = L'';
  211. *(head + i) = L'';
  212. }
  213. else
  214. {
  215. char* head = (char*) recvBuf;
  216. for(UINT i = readstrpos; i<buflength; i++)
  217. {
  218. if(*(head + i) == 'n')break;
  219. }
  220. oldpos = readstrpos;
  221. readstrpos = i+1;
  222. if(i != readstrpos && *(head + i - 1) == 'r')
  223. *(head + i - 1) = '';
  224. *(head + i) = '';
  225. }
  226. return oldpos;
  227. }
  228. BOOL HttpRequest::ReadString(LPWSTR readstr)
  229. {
  230. int pos = HttpRequest::ReadStringEx();
  231. if(pos == -1)return FALSE;
  232. if(fWide)
  233. wcscpy(readstr,(LPCWSTR) recvBuf + pos);
  234. else
  235. {
  236. MultiByteToWideChar(CP_ACP, 0, (LPCSTR) recvBuf + pos, -1, readstr, 2048);
  237. }
  238. return TRUE;
  239. }
  240. BOOL HttpRequest::ReadString(LPSTR readstr)
  241. {
  242. int pos = HttpRequest::ReadStringEx();
  243. if(pos == -1)return FALSE;
  244. if(!fWide)
  245. strcpy(readstr,(LPCSTR) recvBuf + pos);
  246. else
  247. {
  248. WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) recvBuf + pos, -1, readstr, 2048, NULL, NULL);
  249. }
  250. return TRUE;
  251. }
  252. void HttpRequest::InitWrite(DWORD initialbufsize)
  253. {
  254. if(h_File)
  255. {
  256. if(GetFileSize(h_File, NULL) != -1)
  257. {
  258. m_dwOffset = 0;
  259. buflength = UINT_MAX;
  260. return; //a valid file
  261. }
  262. CloseHandle(h_File);
  263. h_File = NULL; //clear the invalid file handle and using inner buffer
  264. initialbufsize = 1024;
  265. }
  266. if(recvBuf)delete[] recvBuf;
  267. recvBuf = new BYTE[initialbufsize + 16];
  268. memset(recvBuf, 0, initialbufsize + 16);
  269. buflength = initialbufsize;
  270. m_dwOffset = 0;
  271. }
  272. BOOL HttpRequest::WriteBuffer(const BYTE* buf, const DWORD m_buflength)
  273. {
  274. if(h_File)
  275. {
  276. DWORD tmpLength = m_buflength;
  277. const BYTE* start = buf;
  278. while(tmpLength > 0)
  279. {
  280. DWORD tmp = 0;
  281. if(WriteFile(h_File, start, tmpLength, &tmp, NULL) == FALSE)
  282. {
  283. errorcode = GetLastError();
  284. return FALSE;
  285. }
  286. tmpLength -= tmp;
  287. start += tmp;
  288. }
  289. }
  290. else
  291. {
  292. if(m_dwOffset + m_buflength > buflength)
  293. {
  294. BYTE* tmp = new BYTE[buflength*3 + 16];
  295. memset(tmp, 0, buflength*3 + 16);
  296. memcpy(tmp, recvBuf, buflength);
  297. delete[] recvBuf;
  298. recvBuf = tmp;
  299. buflength = buflength* 3;
  300. }
  301. memcpy(recvBuf + m_dwOffset, buf, m_buflength);
  302. }
  303. m_dwOffset += m_buflength;
  304. return TRUE;
  305. }
  306. void HttpRequest::InternetCloseHandleAsync(HINTERNET Hcls)
  307. {
  308. if(Hcls == NULL)
  309. return;
  310. ResetEvent(m_hEvent[1]);
  311. if(!InternetCloseHandle(Hcls))
  312. {
  313. if(GetLastError() == ERROR_IO_PENDING)
  314. WaitForSingleObject(m_hEvent[1], INFINITE);
  315. }
  316. SetEvent(m_hEvent[1]);
  317. }
  318. static const TCHAR _defaultContentType[] = _T("Content-Type: application/x-www-form-urlencoded");
  319. DWORD WINAPI HttpRequest::InitialCallback(LPVOID params)
  320. {
  321. /* HttpRequest* pObj = (HttpRequest*) params;
  322. if(::InternetSetStatusCallback(pObj->HSO, AsyncInternetCallback) == INTERNET_INVALID_STATUS_CALLBACK)
  323. pObj->errorcode = 1;
  324. SetEvent(pObj->m_hEvent[0]);*/
  325. return 0;
  326. }
  327. void HttpRequest::MakeHeadMsg(BOOL post, LPTSTR buf)
  328. {
  329. LPTSTR start = buf;
  330. if(post)
  331. {
  332. _tcscpy(start, _defaultContentType);
  333. start += _tcslen(_defaultContentType);
  334. }
  335. if(h_File != NULL)
  336. {
  337. if(m_dwOffset != UINT_MAX)
  338. {
  339. _tcscpy(start, _T("rn"));
  340. if(m_dwOffsetEnd != UINT_MAX)
  341. _stprintf(start, _T("Range: bytes= %d-%d"), m_dwOffset, m_dwOffsetEnd);
  342. else
  343. _stprintf(start, _T("Range: bytes= %d-"), m_dwOffset);
  344. }
  345. }
  346. }
  347. BOOL HttpRequest::OpenRequest(LPCWSTR url, BOOL cache, LPCWSTR send)
  348. {
  349. #ifdef _UNICODE
  350. LPCWSTR purl = url;
  351. #else
  352. char* purl = new char[2048];
  353. WideCharToMultiByte(CP_ACP, 0, url, -1, purl, 2048, NULL, NULL);
  354. #endif
  355. size_t size = 0;
  356. if(send != NULL)
  357. size = wcslen(send) * sizeof(WCHAR);
  358. LPVOID pdata = (LPVOID) send;
  359. if(fWide == FALSE && send != NULL)
  360. {
  361. pdata = (LPVOID) new char[size];
  362. WideCharToMultiByte(CP_ACP, 0, send, -1, (char*) pdata, size, NULL, NULL);
  363. size = strlen((char*) pdata);
  364. }
  365. BOOL ret;
  366. ret = OpenRequestEx(purl, cache, pdata, size);
  367. #ifndef _UNICODE
  368. delete[] purl;
  369. #endif
  370. if(fWide == FALSE && send != NULL)
  371. delete[] pdata;
  372. return ret;
  373. }
  374. BOOL HttpRequest::OpenRequest(LPCSTR url, BOOL cache, LPCSTR send)
  375. {
  376. #ifndef _UNICODE
  377. LPCSTR purl = url;
  378. #else
  379. WCHAR* purl = new WCHAR[2048];
  380. MultiByteToWideChar(CP_ACP, 0, url, -1, purl, 2048);
  381. #endif
  382. DWORD size = 0;
  383. if(send != NULL)
  384. size = strlen(send);
  385. LPVOID pdata = (LPVOID) send;
  386. if(fWide != FALSE && send != NULL)
  387. {
  388. pdata = (LPVOID) new WCHAR[size];
  389. MultiByteToWideChar(CP_ACP, 0, send, -1, (WCHAR*) pdata, size);
  390. size = wcslen((WCHAR*) pdata)*sizeof(WCHAR);
  391. }
  392. BOOL ret;
  393. ret = OpenRequestEx(purl, cache, pdata, size);
  394. #ifdef _UNICODE
  395. delete[] purl;
  396. #endif
  397. if(fWide != FALSE && send != NULL)
  398. delete[] pdata;
  399. return ret;
  400. }
  401. BOOL HttpRequest::OpenRequestEx(LPCTSTR url, BOOL cache, const void* send, DWORD sendsize)
  402. {
  403. HANDLE hSemaphore = ::OpenSemaphore(SEMAPHORE_ALL_ACCESS | SEMAPHORE_MODIFY_STATE | SYNCHRONIZE
  404. , NULL, HTTP_REQUEST_LIMIT_NAME);
  405. BOOL funOK = FALSE;
  406. HINTERNET HSO = NULL; 
  407. HINTERNET HIO = NULL;
  408. HINTERNET HQO = NULL;
  409. TCHAR* p_stN = new TCHAR[256];
  410. TCHAR* p_flN = new TCHAR[2048];
  411. TCHAR* p_bufstr = new TCHAR[1024];
  412. BYTE* p_buf = new BYTE[1024];
  413. DWORD port = 80;
  414. __try{
  415. if(!ParseURL(url, p_stN, p_flN, &port))
  416. {
  417. errorcode = ERROR_INTERNET_NAME_NOT_RESOLVED;
  418. __leave;
  419. }
  420. if(hSemaphore)
  421. {
  422. DWORD ret = ::WaitForSingleObject(hSemaphore, Connect_timeout*2);
  423. if(ret == WAIT_TIMEOUT)
  424. {
  425. errorcode = 12002;
  426. __leave;
  427. }
  428. else if(ret == WAIT_ABANDONED)
  429. {
  430. errorcode = USER_STOP;
  431. __leave;
  432. }
  433. }
  434. DWORD type; LPCTSTR proxystr = NULL;
  435. switch(b_useproxy)
  436. {
  437. case 0: type = INTERNET_OPEN_TYPE_DIRECT;break;
  438. case 1: type = INTERNET_OPEN_TYPE_PRECONFIG;break;
  439. case 2: type = INTERNET_OPEN_TYPE_PROXY;
  440. proxystr = m_proxystr;
  441. break;
  442. default: type = INTERNET_OPEN_TYPE_PRECONFIG;break;
  443. }
  444. HSO = ::InternetOpen(INTERNET_CONNECT_ADAGENT, type, proxystr, NULL, INTERNET_FLAG_ASYNC);
  445. if(HSO == NULL)
  446. {
  447. errorcode = GetLastError();
  448. __leave;
  449. }
  450. if(::InternetSetStatusCallback(HSO, AsyncInternetCallback) == INTERNET_INVALID_STATUS_CALLBACK)
  451. {
  452. errorcode = GetLastError();
  453. __leave;
  454. }
  455. HDResetEvent();
  456. HIO = InternetConnect(HSO, p_stN, (WORD) port , NULL,NULL,
  457.             INTERNET_SERVICE_HTTP , 0, reinterpret_cast<DWORD>(this));
  458. if(HIO == NULL)
  459. {
  460. if(WaitingEvent(Connect_timeout))
  461. __leave;
  462. HIO = m_hInternet;
  463. }
  464.   
  465.       // 3.初始化下载请求
  466. const TCHAR AcceptType[] = _T("*/*");
  467. LPCTSTR p_FA[] = {AcceptType, NULL};
  468. TCHAR Verb[10];
  469. if(send != NULL)
  470. _tcscpy(Verb, _T("POST"));
  471. else
  472. _tcscpy(Verb, _T("GET"));
  473. if(!cache)
  474. type = INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD;
  475. else
  476. type = 0;
  477. HDResetEvent();
  478.     HQO = HttpOpenRequest(HIO,
  479.             Verb, // 从服务器获取数据
  480.             p_flN, // 想读取的文件的名称
  481.             _T("HTTP/1.1"), // 使用的协议
  482.             NULL,
  483.             p_FA,
  484.             type,
  485.             reinterpret_cast<DWORD>(this));
  486.       // 4.发送下载请求
  487. *p_bufstr = 0;
  488. MakeHeadMsg(send != NULL, p_bufstr);
  489. BOOL ret;
  490. if(*p_bufstr == 0)
  491. ret = HttpSendRequest(HQO, NULL, 0, NULL, 0);
  492. else if(send != NULL)
  493. ret = HttpSendRequest(HQO, p_bufstr, _tcslen(p_bufstr), (LPVOID) send, sendsize);
  494. else
  495. ret = HttpSendRequest(HQO, p_bufstr, _tcslen(p_bufstr), NULL, 0);
  496.     if(!ret)
  497. {
  498. if(WaitingEvent(Connect_timeout))
  499. __leave;
  500. }
  501. DWORD length, result;
  502. result = 32774; //ERROR_HTML
  503. length = sizeof(result);
  504. if(!::HttpQueryInfo(HQO , HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER
  505. , &result, &length, NULL))
  506. {
  507. errorcode = GetLastError();
  508. __leave;
  509. }
  510. if(result != 200 && result != 206)
  511. {
  512. errorcode = result;
  513. __leave;
  514. }
  515. result = UINT_MAX;
  516. /* TCHAR* tbuf = new TCHAR[1024];
  517. length = 1024;
  518. ::HttpQueryInfo(HQO , HTTP_QUERY_RAW_HEADERS_CRLF , tbuf, &length, NULL);*/
  519. ::HttpQueryInfo(HQO , HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &result, &length, NULL);
  520. if(result == UINT_MAX)
  521. result = 1024;
  522. else
  523. result += 1; //避免一次无效的扩展缓冲区
  524. //downloading
  525. InitWrite(result);
  526. //**********the internetreadfileexW can't not be used for some reason *************//
  527. INTERNET_BUFFERSA i_buf = {0};
  528. i_buf.dwStructSize = sizeof(INTERNET_BUFFERSA);
  529. i_buf.lpcszHeader = NULL;
  530. i_buf.dwBufferLength = 1024;
  531. i_buf.lpvBuffer = p_buf;
  532. while(1)
  533. {
  534. HDResetEvent();
  535. if (FALSE == ::InternetReadFileExA(HQO , &i_buf, IRF_ASYNC, reinterpret_cast<DWORD>(this)))
  536. {
  537. if(WaitingEvent(Request_timeout))
  538. __leave;
  539. }
  540. else
  541. {
  542. //在网络传输速度快,步长较小的情况下,
  543. //InternetReadFileEx 经常会直接返回成功,
  544. //因此要判断是否发生了用户要求终止子线程事件。
  545. if (WAIT_OBJECT_0 == ::WaitForSingleObject(m_hEvent[0], 0))
  546. {
  547. errorcode = USER_STOP;
  548. __leave;
  549. }
  550. }
  551. if(i_buf.dwBufferLength == 0)
  552. break;
  553. if(!WriteBuffer(p_buf, i_buf.dwBufferLength))
  554. __leave;
  555. i_buf.dwBufferLength = 1024;
  556. i_buf.lpvBuffer = p_buf;
  557. }
  558. readstrpos = 0;
  559. buflength = m_dwOffset;
  560. funOK = TRUE;
  561.   }
  562.   __finally
  563.   {
  564. InternetCloseHandleAsync(HQO);
  565. InternetCloseHandleAsync(HSO);
  566. if(hSemaphore)
  567. ::ReleaseSemaphore(hSemaphore, 1, NULL);
  568. delete[] p_stN;
  569. delete[] p_flN;
  570. delete[] p_buf;
  571. delete[] p_bufstr;
  572.   }
  573.   return funOK;
  574. }
  575. BOOL HttpRequest::ParseURL(LPCTSTR src, LPTSTR stN, LPTSTR flN, DWORD* port)
  576. {
  577.    TCHAR* p_src = new TCHAR[4096];
  578.    _tcscpy(p_src, src);
  579.    TCHAR* tmp = _tcsstr(p_src, _T("http://"));
  580.    if(tmp == NULL || (p_src - tmp) != 0)
  581.    {
  582.    delete[] p_src;
  583.    return FALSE;
  584.    }
  585.    tmp = _tcschr(p_src + 7, _T('/'));
  586.    if(tmp == NULL)
  587.    {
  588.    flN[0] = 0;
  589.    _tcscpy(stN, p_src + 7);
  590.    }
  591.    else
  592.    {
  593.    *tmp = 0;
  594.    _tcscpy(stN, p_src + 7);
  595.    *tmp = _T('/');
  596.    _tcscpy(flN, tmp);
  597.    }
  598. tmp = _tcschr(stN, _T(':'));
  599. if(tmp == NULL)
  600. *port = 80;
  601. else
  602. {
  603. *tmp = 0;
  604. *port = _ttoi(tmp + 1);
  605. }
  606.    delete[] p_src;
  607.    return TRUE;
  608. }
  609. void CALLBACK HttpRequest::AsyncInternetCallback(
  610.     HINTERNET hInternet,
  611. DWORD dwContext,
  612. DWORD dwInternetStatus,
  613. LPVOID lpvStatusInformation,
  614. DWORD dwStatusInformationLength)
  615. {
  616.     HttpRequest * pObj = reinterpret_cast<HttpRequest*>(dwContext);
  617.     switch(dwInternetStatus)
  618.     {
  619.     //句柄被创建
  620.     case INTERNET_STATUS_HANDLE_CREATED:
  621.     pObj->m_hInternet = (HINTERNET)(((LPINTERNET_ASYNC_RESULT)
  622.      (lpvStatusInformation))->dwResult);
  623.     break;
  624.    //句柄被关闭
  625.    case INTERNET_STATUS_HANDLE_CLOSING:
  626. ::SetEvent(pObj->m_hEvent[1]);
  627.     break;
  628.    //一个请求完成,比如一次句柄创建的请求,或者一次读数据的请求
  629.    case INTERNET_STATUS_REQUEST_COMPLETE:
  630.    //如果发生错误,则设置子线程退出事件
  631.      //这里也是一个陷阱,经常会忽视处理这个错误,
  632.    DWORD ret;
  633.     if (( ret = ((LPINTERNET_ASYNC_RESULT) (lpvStatusInformation))->dwError) != ERROR_SUCCESS)
  634.       pObj->errorcode = ret;
  635. else
  636. pObj->errorcode = 0;
  637. ::SetEvent(pObj->m_hEvent[1]);
  638.     break;
  639. //连接中断
  640. case INTERNET_STATUS_CONNECTION_CLOSED:
  641.    break;
  642. //重定向连接
  643. case INTERNET_STATUS_REDIRECT:
  644.    break;
  645. //已连接
  646. case INTERNET_STATUS_CONNECTED_TO_SERVER:
  647.    break;
  648. //解析服务器
  649. case INTERNET_STATUS_RESOLVING_NAME:
  650. break;
  651. case INTERNET_STATUS_REQUEST_SENT:
  652.    break;
  653.    }
  654. }