httpget及httppost

  1. #pragma once
  2. /*
  3. * HttpClient同步类
  4. * 暂时只实现[方案二]
  5. * 使用[方案一]:
  6. * #include "SyncHttpClient.h"
  7. * int main()
  8. * {
  9. *   CSyncHttpClient syncClient;
  10. *   BYTE pData[1024];
  11. *   uint16  uSize = 1024;
  12. *   syncClient.SetHost(TEXT("192.168.1.1"));
  13. *   syncClient.SetPort(8000);                   
  14. *   syncClient.SetProgram(TEXT("/program"));    //.............or use default
  15. *   if(syncClient.Request(pData, uSize))
  16. *   {
  17. *     BYTE *bRcvBuf = NULL;
  18. *     uint16 uBufSize = 4069;
  19. *     uint16 uPerTime = 512;
  20. *     
  21. *      if(syscClient.QueryContentLength(&uBufSize))
  22. *      {
  23. *        try{
  24. *          bRcvBuf = new BYTE[nBufSize];
  25. *        }
  26. *        catch(...)
  27. *        {
  28. *          return;
  29. *        }
  30. *        if(syncClient.GetResponse(bRcvBuf, uBufSize, uPerTime))
  31. *        {
  32. *          //deal the data
  33. *          delete []bRcvBuf;   
  34. *        }
  35. *      }
  36. *   }
  37. * }
  38. * [方案二]:
  39. * #include "SyncHTTPClient.h"
  40. * class CClientTest:IDataSubscriber
  41. * {
  42. * public:
  43. *   //收到数据包
  44. *   virtual void OnPacketReceived(void *pData, UINT16 uSize){//dealit};
  45. *   //数据进度
  46. *   virtual void OnRecvDataPercent(IN BYTE nPercent){//update progress};
  47. *   //数据接收出错
  48. *   virtual void OnRcvError(IN INT16 nError){//report for error};
  49. * };
  50. * int DoRequest(void *pData, short uLen)
  51. * {
  52. *   CClientTest test;
  53. *   CNetDataAdapter ada(test);  //ada回主动找CConnectionManager要host等的配置
  54. *   ada.Request(pData, uLen);
  55. *   return 0;
  56. * }
  57. *
  58. */
  59. #include <wininet.h>
  60. #include "DataInterface.h"
  61. #define  _DEFAULT_HOST TEXT("192.168.1.10")
  62. #define  _DEFAULT_PORT 80
  63. #define  _DEFAULT_PROG TEXT("/test")
  64. #define  _DEFAULT_MAX_RCV_BUF_SIZE 8192 * 20
  65. #define  _DEFAULT_RECV_BUF_UNIT 4096
  66. #define  _DEFAULT_REFERER_LENGTH 30
  67. class CAsyncHttpClient :IDataCommunicater
  68. {
  69.     friend class CConnectManager;
  70. public:
  71.     enum
  72.     {
  73.         STATUS_LAZY = 0,        //空闲
  74.         STATUS_BUSING,          //忙
  75.         STATUS_FINISH           //结束
  76.     };
  77.     enum
  78.     {
  79.         ERR_MEMORY_EXPRESS = -100,          //内存过大,超过m_dwMaxSize限制
  80.         ERR_MEMORY_HEAP_FAILED,             //HeapCreate失败
  81.         ERR_INET_OPEN_FAILED,               //InternetOpen失败
  82.         ERR_INET_CONNECT_FAILED,            //InternetConnect失败
  83.         ERR_INET_REQUEST_FAILED,            //HttpOpenRequest失败
  84.         ERR_INET_RESPONSE,                  //返回不为200
  85.         ERR_INET_CONTENT_LENGTH,            //无法得到长度
  86.         ERR_INET_READ,                      //读数据出错
  87.         ERR_INET_FINISH = 0,                //没有错误
  88.         ERR_INET_START                      //开始
  89.         
  90.     };
  91. public:
  92.     CAsyncHttpClient(void);
  93.     ~CAsyncHttpClient(void);
  94.     //post对象配置
  95. public:
  96.     //设置主机
  97.     void SetPostHost(const TCHAR* szHost = _DEFAULT_HOST);
  98.     //设置主机端口
  99.     void SetHostPort(unsigned short uPort = _DEFAULT_PORT);
  100.     //设置程序
  101.     void SetPostProgram(const TCHAR* szProgram = _DEFAULT_PROG);
  102.     //设置Session,通常一个程序只需要一个Session,即InternetOpen返回的句柄
  103.     void SetSession(HINTERNET hSession = 0);
  104.     //IDataCommunicater接口
  105. public:
  106.     //注册订阅者
  107.     virtual bool RegisterSubscriber(HWND aSubscriber);
  108.     //取消订阅者
  109.     virtual bool RemoveSubscirber(HWND aSubscriber);
  110.     //是否繁忙
  111.     virtual bool IsBusy() const;
  112.     //发送流
  113.     virtual bool Request(void* aData, DWORD uSize);
  114.     //get请法
  115.     virtual bool HttpGet(TCHAR* szFile);
  116.     //取消发送
  117.     virtual void Cancel();
  118.     //销毁资源
  119.     virtual void Close();
  120. private:
  121.     void OnWork();
  122.     //状态回调函数
  123. private:
  124.     static void CALLBACK StatusCallback(HINTERNET hInternet,
  125.         DWORD_PTR dwContext,
  126.         DWORD dwInternetStatus,
  127.         LPVOID lpvStatusInformation,
  128.         DWORD dwStatusInformationLength);
  129.     //数据读取例程
  130.     static DWORD CALLBACK ThreadEntry(LPVOID pThis);
  131.     //辅助函数
  132. private:
  133.     //判断内存是否足够,不足按指定的粒度分配
  134.     bool EnsureEnoughSpace(DWORD dwRequired = 0);
  135.     //释放内存资源
  136.     void ReleaseResource();
  137.     //完成请求
  138.     void SetCompleteRequest();
  139.     //等待完成请求
  140.     bool WaitCompleteRequest(unsigned long ntime=INFINITE);
  141.     //状态机转换
  142.     bool SetState(short uState);
  143.     short GetState();
  144.     //设置进度条
  145.     void SetProgress(int nStep);
  146.     //创建读数据线程
  147.     void BeginAsyncRead();
  148.     //主机信息与缓存
  149. private:
  150.     //主机 ip/name
  151.     TCHAR* m_pszHost;
  152.     //端口
  153.     unsigned short m_uPort;
  154.     //程序
  155.     TCHAR* m_pszProg;
  156.     
  157.     //缓冲区
  158.     const char* m_pData;
  159.     DWORD       m_dwContentSize;
  160.     //最大容量,超过此容量,会自动分配
  161.     DWORD       m_dwMaxSize;
  162.     //单元容量,当内存不足时,按此容量增加分配
  163.     DWORD       m_dwUnitSize;        
  164.     //当前容量
  165.     DWORD       m_dwCurSize;
  166.     
  167.     //服务状态
  168. private:
  169.     //服务正所处的状态
  170.     //InternetOpen
  171.     //InternetConnect
  172.     //HttpOpenRequest
  173.     //HttpAddRequestHeaders
  174.     //HttpSendRequest
  175.     //HttpQueryInfo 查询是否成功
  176.     //              读数据长度
  177.     //InternetReadFile 读数据
  178.     //                 重新分配缓存
  179.     //                 处理完毕
  180.     short  m_uSeviceState;
  181.     HINTERNET      _hSession;
  182.     HINTERNET      _hConn;
  183.     HINTERNET      _hRequest;
  184.     
  185.     bool           _bCloseSession;  //如果不是公用的(SetSession),则要关闭
  186.     //订阅客户
  187. private:
  188.     //订阅数据的客户,目前只支持一个订阅者
  189.     HWND  m_pCS;
  190.     //堆内存管理
  191. private:
  192.     //heap堆句柄
  193.     HANDLE  _hHeap;
  194.     //同步事件,请求已完成
  195.     HANDLE       _hCompleteRequestEvent;
  196.     //提取数据线程句柄
  197.     HANDLE      _hThread;
  198.     DWORD       _dwThreadID;
  199.     int         m_nPercents;
  200. };

  1. #include "StdAfx.h"
  2. #include "AsyncHttpClient.h"
  3. #define SAFE_DELARRAY(arr) if(arr){delete[] arr;arr = NULL;}
  4. CAsyncHttpClient::CAsyncHttpClient(void)
  5. :m_pszHost(NULL)
  6. ,m_uPort(_DEFAULT_PORT)
  7. ,m_pszProg(NULL)
  8. ,m_pData(NULL)
  9. ,m_dwContentSize(0)
  10. ,m_dwMaxSize(_DEFAULT_MAX_RCV_BUF_SIZE)
  11. ,m_dwUnitSize(_DEFAULT_RECV_BUF_UNIT)
  12. ,m_dwCurSize(0)
  13. ,m_uSeviceState(STATUS_LAZY)
  14. ,_hSession(0)
  15. ,_hConn(0)
  16. ,_hRequest(0)
  17. ,_bCloseSession(true)
  18. ,m_pCS(NULL)
  19. ,_hHeap(0)
  20. ,_hCompleteRequestEvent(INVALID_HANDLE_VALUE)
  21. ,_hThread(INVALID_HANDLE_VALUE)
  22. ,_dwThreadID(0)
  23. ,m_nPercents(0)
  24. {
  25. }
  26. CAsyncHttpClient::~CAsyncHttpClient(void)
  27. {
  28.     Close();
  29.     //释放内存
  30.     ReleaseResource();
  31. }
  32. //------------------------------------------------------------------------
  33. //设置
  34. //------------------------------------------------------------------------
  35. //设置主机
  36. void CAsyncHttpClient::SetPostHost(const TCHAR* szHost/* = _DEFAULT_HOST*/throw()
  37. {
  38.     if(m_uSeviceState != STATUS_LAZY)
  39.     {
  40.         return;
  41.     }
  42.     unsigned short uSize = _tcslen(szHost);
  43.     if(uSize == 0){
  44.         return;
  45.     }
  46.     
  47.     SAFE_DELARRAY(m_pszHost);
  48.     m_pszHost = new TCHAR[uSize+1];
  49.     if(m_pszHost == NULL)
  50.     {
  51.         return;
  52.     }
  53.     CopyMemory(m_pszHost, szHost, sizeof(TCHAR) * uSize);
  54.     m_pszHost[uSize] = '/0';
  55.     return;
  56. }
  57. //设置主机端口
  58. void CAsyncHttpClient::SetHostPort(unsigned short uPort/* = _DEFAULT_PORT*/throw ()
  59. {
  60.     if(m_uSeviceState != STATUS_LAZY)
  61.     {
  62.         return;
  63.     }
  64.     m_uPort = uPort;
  65.     return;
  66. }
  67. //设置程序
  68. void CAsyncHttpClient::SetPostProgram(const TCHAR* szProgram/* = _DEFAULT_PROG*/)
  69. {
  70.     if(m_uSeviceState != STATUS_LAZY)
  71.     {
  72.         return;
  73.     }
  74.     unsigned short uSize = _tcslen(szProgram);
  75.     if(uSize == 0){
  76.         return;
  77.     }
  78.     
  79.     SAFE_DELARRAY(m_pszProg);
  80.     m_pszProg = new TCHAR[uSize+1];
  81.     if(m_pszProg == NULL)
  82.     {
  83.         return;
  84.     }
  85.     CopyMemory(m_pszProg, szProgram, sizeof(TCHAR) * uSize);
  86.     m_pszProg[uSize] = '/0';
  87.     return;
  88. }
  89. //设置Session,通常一个程序只需要一个Session,即InternetOpen返回的句柄
  90. void CAsyncHttpClient::SetSession(HINTERNET hSession/* = 0*/
  91. {
  92.     if(hSession == 0) return;
  93.     if(m_uSeviceState != STATUS_LAZY)
  94.     {
  95.         return;
  96.     }
  97.     
  98.     _hSession = hSession;
  99.     _bCloseSession = false;
  100.     return;
  101. }
  102. //------------------------------------------------------------------------
  103. //IDataCommunicater接口
  104. //------------------------------------------------------------------------
  105. //注册订阅者
  106. bool CAsyncHttpClient::RegisterSubscriber(HWND aSubscriber)
  107. {
  108.     if(!aSubscriber) return false;
  109.     m_pCS = aSubscriber;
  110.     return true;
  111. }
  112. //取消订阅者
  113. bool CAsyncHttpClient::RemoveSubscirber(HWND aSubscriber)
  114. {
  115.     if(aSubscriber != m_pCS) return false;
  116.     m_pCS = NULL;
  117.     return true;
  118. }
  119. //是否繁忙
  120. bool CAsyncHttpClient::IsBusy() const
  121. {
  122.     return m_uSeviceState != STATUS_LAZY && STATUS_FINISH != m_uSeviceState;
  123. }
  124. //发送流
  125. bool CAsyncHttpClient::Request(void* aData, DWORD uSize)
  126. {
  127.     if(IsBusy()) return false;
  128.     if(m_pszHost == NULL)
  129.         SetPostHost();
  130.     if(m_uPort == 0)
  131.         SetHostPort();
  132.     if(m_pszProg == NULL)
  133.         SetPostProgram();
  134.     if(_hCompleteRequestEvent == INVALID_HANDLE_VALUE)
  135.     {
  136.         _hCompleteRequestEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  137.     }
  138.     const TCHAR* pszAccepts[] = {L"*/*", NULL};
  139.     TCHAR szReferer[_DEFAULT_REFERER_LENGTH] = {0};
  140.     
  141. #ifdef _UNICODE
  142.     wsprintf(szReferer, L"%s:%d", m_pszHost, m_uPort);
  143. #else
  144.     sprintf(szReferer, "%s:%d", m_pszHost, m_uPort);
  145. #endif
  146.     m_uSeviceState = STATUS_BUSING;
  147.     if(m_pCS)
  148.     {
  149.         PostMessage(m_pCS, WM_STATUS, ERR_INET_START, 0);
  150.     }
  151.     if(_hSession == NULL)
  152.     {
  153.         //打开
  154.         _hSession = ::InternetOpen(TEXT("Agent")
  155.                                                         ,INTERNET_OPEN_TYPE_PRECONFIG
  156.                                                             ,NULL   //从注册表里读代理信息
  157.                                                             ,NULL
  158.                                                             ,INTERNET_FLAG_ASYNC);  //异步连接
  159.         if(NULL == _hSession || _hSession == INVALID_HANDLE_VALUE)
  160.         {
  161.             if(m_pCS)
  162.             {
  163.                 PostMessage(m_pCS, WM_STATUS, ERR_INET_OPEN_FAILED, 0);
  164.             }
  165.             //取消
  166.             Cancel();
  167.             return false;
  168.         }
  169.         _bCloseSession = true;
  170.     }
  171.     //设置回调函数
  172.     INTERNET_STATUS_CALLBACK pc=::InternetSetStatusCallback(_hSession, (INTERNET_STATUS_CALLBACK)this->StatusCallback);
  173.     if(pc == INTERNET_INVALID_STATUS_CALLBACK)
  174.     {
  175.         if(m_pCS)
  176.         {
  177.             PostMessage(m_pCS, WM_STATUS, ERR_INET_OPEN_FAILED, 0);
  178.         }
  179.         //取消
  180.         Cancel();
  181.         return false;
  182.     }
  183.     if(NULL == _hConn)
  184.     {
  185.         //链接
  186.         _hConn = ::InternetConnect(_hSession
  187.                                                         ,m_pszHost
  188.                                                         ,m_uPort   //ip and port
  189.                                                         ,L""
  190.                                                         ,L""    //username and pwd
  191.                                                         ,INTERNET_SERVICE_HTTP
  192.                                                         ,0
  193.                                                         ,reinterpret_cast<unsigned long>(this));  //传到回调函数的自定义参数
  194.         if(NULL == _hConn || INVALID_HANDLE_VALUE == _hConn)
  195.         {
  196.             if(m_pCS)
  197.             {
  198.                 PostMessage(m_pCS, WM_STATUS, ERR_INET_CONNECT_FAILED, 0);
  199.             }
  200.             //取消
  201.             Cancel();
  202.             return false;
  203.         }
  204.     }
  205.                 
  206.     //请求网页
  207.     _hRequest = ::HttpOpenRequest(_hConn
  208.                                                             ,L"POST"
  209.                                                             ,m_pszProg
  210.                                                             ,NULL          //使用http/1.0
  211.                                                             ,szReferer
  212.                                                             ,pszAccepts    //accept */*
  213.                                                             ,INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_CACHE_WRITE
  214.                                                             ,reinterpret_cast<unsigned long>(this));//传到回调函数的自定义参数
  215.     if(NULL == _hRequest || _hRequest==INVALID_HANDLE_VALUE)
  216.     {
  217.         if(m_pCS)
  218.         {
  219.             PostMessage(m_pCS, WM_STATUS, ERR_INET_REQUEST_FAILED, 0);
  220.         }
  221.         //取消
  222.         Cancel();
  223.         return false;
  224.     }
  225.     更改请求头
  226.     //if(FALSE == ::HttpAddRequestHeaders( _hRequest, L"Accept: */*/r/n", _tcslen(L"Accept: */*/r/n"), HTTP_ADDREQ_FLAG_REPLACE))
  227.     //{
  228.     //  sError.Format(L"HttpAddRequestHeaders不能打开 NO = %d", GetLastError());
  229.     //  ThrowError(sError);
  230.     //  goto ERROR_RELEASE;
  231.     //}
  232.     //开始发请求
  233.     static INTERNET_BUFFERS InternetBufferIn = {0};
  234.     InternetBufferIn.dwStructSize = sizeof(INTERNET_BUFFERS);
  235.     InternetBufferIn.Next = NULL;
  236.     InternetBufferIn.lpcszHeader = NULL;
  237.     InternetBufferIn.dwHeadersLength = 0;
  238.     InternetBufferIn.lpvBuffer = aData;        //post的数据
  239.     InternetBufferIn.dwBufferLength = uSize;   //数据长度
  240.     //发出请求
  241.     if(FALSE == ::HttpSendRequestEx(_hRequest
  242.                                     ,&InternetBufferIn
  243.                                     ,NULL
  244.                                     ,0
  245.                                     ,reinterpret_cast<unsigned long>(this))
  246.         &&::GetLastError()!=ERROR_IO_PENDING)
  247.     {
  248.         if(m_pCS)
  249.         {
  250.             PostMessage(m_pCS, WM_STATUS, ERR_INET_REQUEST_FAILED, 0);
  251.         }
  252.         //取消
  253.         Cancel();
  254.         return false;
  255.     }
  256.     SetProgress(10);
  257.     //等待10s,否则返回失败
  258.     if(WaitCompleteRequest(10 * 1000) == false)
  259.     {
  260.         if(m_pCS)
  261.         {
  262.             PostMessage(m_pCS, WM_STATUS, ERR_INET_REQUEST_FAILED, 0);
  263.         }
  264.         //取消
  265.         Cancel();
  266.         return false;
  267.     }
  268.     SetProgress(20);
  269.     //请求结束
  270.     if(!::HttpEndRequest(_hRequest, NULL, 0, reinterpret_cast<unsigned long>(this))
  271.         &&::GetLastError()!=ERROR_IO_PENDING)
  272.     {
  273.         if(m_pCS)
  274.         {
  275.             PostMessage(m_pCS, WM_STATUS, ERR_INET_REQUEST_FAILED, 0);
  276.         }
  277.         //取消
  278.         Cancel();
  279.         return false;
  280.     }
  281.   //创建读数据线程
  282.     _hThread = CreateThread(NULL
  283.                         , 0
  284.                         ,(LPTHREAD_START_ROUTINE)ThreadEntry
  285.                         ,LPVOID(this)
  286.                         , 0
  287.                         ,&_dwThreadID);
  288.     if(_hThread == 0 || _hThread == INVALID_HANDLE_VALUE)
  289.     {
  290.         if(m_pCS)
  291.         {
  292.             PostMessage(m_pCS, WM_STATUS, ERR_INET_REQUEST_FAILED, 0);
  293.         }
  294.         //取消
  295.         Cancel();
  296.         return false;
  297.     }
  298.     SetProgress(10);
  299.     return true;
  300. }
  301. bool CAsyncHttpClient::HttpGet(TCHAR* szFile)
  302. {
  303.     if(IsBusy()) return false;
  304.     if(_hCompleteRequestEvent == INVALID_HANDLE_VALUE)
  305.     {
  306.         _hCompleteRequestEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  307.     }
  308.     const TCHAR* pszAccepts[] = {L"*/*", NULL};
  309.     if(m_pCS)
  310.     {
  311.         PostMessage(m_pCS, WM_STATUS, ERR_INET_START, 0);
  312.     }
  313.     if(_hSession == NULL)
  314.     {
  315.         //打开
  316.         _hSession = ::InternetOpen(TEXT("TGUIDE")
  317.             ,INTERNET_OPEN_TYPE_PRECONFIG
  318.             ,NULL   //从注册表里读代理信息
  319.             ,NULL
  320.             ,INTERNET_FLAG_ASYNC);  //异步连接
  321.         if(NULL == _hSession || _hSession == INVALID_HANDLE_VALUE)
  322.         {
  323.             if(m_pCS)
  324.             {
  325.                 PostMessage(m_pCS, WM_STATUS, ERR_INET_OPEN_FAILED, 0);
  326.             }
  327.             //取消
  328.             Cancel();
  329.             return false;
  330.         }
  331.         _bCloseSession = true;
  332.     }
  333.     //设置回调函数
  334.     INTERNET_STATUS_CALLBACK pc=::InternetSetStatusCallback(_hSession, (INTERNET_STATUS_CALLBACK)this->StatusCallback);
  335.     if(pc == INTERNET_INVALID_STATUS_CALLBACK)
  336.     {
  337.         if(m_pCS)
  338.         {
  339.             PostMessage(m_pCS, WM_STATUS, ERR_INET_OPEN_FAILED, 0);
  340.         }
  341.         //取消
  342.         Cancel();
  343.         return false;
  344.     }
  345.     if(NULL == (_hRequest = InternetOpenUrl(_hSession
  346.                                   , szFile                         //地址
  347.                                                             , NULL                           //头
  348.                                                             , 0                              //头的长度
  349.                                                             , INTERNET_FLAG_RELOAD           //标志
  350.                                                             , reinterpret_cast<unsigned long>(this))) &&::GetLastError()!=ERROR_IO_PENDING)
  351.     {
  352.         if(m_pCS)
  353.         {
  354.             PostMessage(m_pCS, WM_STATUS, ERR_INET_REQUEST_FAILED, 0);
  355.         }
  356.         //取消
  357.         Cancel();
  358.         return false;
  359.     }
  360.     SetProgress(10);
  361.     //等待10s,否则返回失败
  362.     if(WaitCompleteRequest(10 * 1000) == false)
  363.     {
  364.         if(m_pCS)
  365.         {
  366.             PostMessage(m_pCS, WM_STATUS, ERR_INET_REQUEST_FAILED, 0);
  367.         }
  368.         //取消
  369.         Cancel();
  370.         return false;
  371.     }
  372.     SetProgress(20);
  373.     //创建读数据线程
  374.     _hThread = CreateThread(NULL
  375.         , 0
  376.         ,(LPTHREAD_START_ROUTINE)ThreadEntry
  377.         ,LPVOID(this)
  378.         , 0
  379.         ,&_dwThreadID);
  380.     if(_hThread == 0 || _hThread == INVALID_HANDLE_VALUE)
  381.     {
  382.         if(m_pCS)
  383.         {
  384.             PostMessage(m_pCS, WM_STATUS, ERR_INET_REQUEST_FAILED, 0);
  385.         }
  386.         //取消
  387.         Cancel();
  388.         return false;
  389.     }
  390.     SetProgress(10);
  391.     SetCompleteRequest();
  392.     return true;
  393. }
  394. //取消发送
  395. void CAsyncHttpClient::Cancel()
  396. {
  397.     if(_hRequest){
  398.         ::InternetCloseHandle(_hRequest);
  399.         _hRequest = 0;
  400.     }
  401.     if(_hConn)
  402.     {
  403.         ::InternetCloseHandle(_hConn);
  404.         _hConn = 0;
  405.     }
  406.     //如果任务未完成,就取消,则要重置缓冲区,清除接收缓冲区
  407.     //if(1/*STATUS_FINISH != m_uSeviceState*/)
  408.     //{
  409.     //  m_dwContentSize = 0;
  410.     //  if(m_pData)
  411.     //  {
  412.     //      ATLASSERT(_hHeap);
  413.     //      BOOL bRet = ::HeapFree(_hHeap, HEAP_NO_SERIALIZE, (LPVOID)m_pData);
  414.     //      ATLASSERT(bRet);
  415.     //      bRet = HeapDestroy(_hHeap);
  416.     //      ATLASSERT(bRet);
  417.     //  }
  418.     //  m_dwCurSize = 0;
  419.     //}
  420.     if(m_pData)
  421.     {
  422.         //ASSERT(_hHeap);
  423.         //BOOL bRet = ::HeapFree(_hHeap, HEAP_NO_SERIALIZE, (LPVOID)m_pData);
  424.         //ASSERT(bRet);
  425.         //bRet = HeapDestroy(_hHeap);
  426.         //ASSERT(bRet);
  427.         SAFE_DELARRAY(m_pData);
  428.         m_dwCurSize = 0;
  429.         m_dwContentSize = 0;
  430.     }
  431.     m_dwContentSize = 0;
  432.     m_uSeviceState = STATUS_LAZY;
  433. }
  434. //销毁资源
  435. void CAsyncHttpClient::Close()
  436. {
  437.     Cancel();
  438.     if(_bCloseSession && _hSession)
  439.     {
  440.         ::InternetCloseHandle(_hSession);
  441.         _hSession = 0;
  442.     }
  443.     ReleaseResource();
  444. }
  445. //------------------------------------------------------------------------
  446. //实现IWorkThread接口
  447. //------------------------------------------------------------------------
  448. void CAsyncHttpClient::OnWork()
  449. {
  450.     //while(true)
  451.     //{
  452.         //等待发送请求事件,等待10秒
  453.         if(!WaitCompleteRequest(10*1000))
  454.         {
  455.             if(m_pCS)
  456.             {
  457.                 PostMessage(m_pCS, WM_STATUS, ERR_INET_REQUEST_FAILED, 0);
  458.             }
  459.             //取消
  460.             Cancel();
  461.             goto DO_RELEASE;;
  462.         }
  463.         //获取数据长度
  464.         DWORD dwTotalSize = 0;
  465.         DWORD dwStatusSize = sizeof(dwTotalSize);
  466.         if(FALSE == ::HttpQueryInfo(_hRequest, HTTP_QUERY_CONTENT_LENGTH| HTTP_QUERY_FLAG_NUMBER, &dwTotalSize, &dwStatusSize, 0))
  467.         {
  468.             //if(m_pCS)
  469.             //  m_pCS->OnRcvError(ERR_INET_CONTENT_LENGTH);
  470.         }
  471.         //读数据
  472.         DWORD dwPerRead = m_dwUnitSize;
  473.         DWORD dwReaded = 0;
  474.         m_dwContentSize = 0;
  475.         if(!InternetQueryDataAvailable(_hRequest
  476.                                    ,&dwPerRead
  477.                                    ,0
  478.                                    ,0))
  479.         {
  480.             //等数据2秒,否则失败
  481.             if(!WaitCompleteRequest(10*1000))
  482.             {
  483.                 if(m_pCS)
  484.                 {
  485.                     PostMessage(m_pCS, WM_STATUS, ERR_INET_REQUEST_FAILED, 0);
  486.                 }
  487.                 //取消
  488.                 Cancel();
  489.                 goto DO_RELEASE;;
  490.             }
  491.         }
  492.         if(EnsureEnoughSpace(dwPerRead) == falsegoto DO_RELEASE;;
  493.         
  494.         BYTE bPercent = 0;
  495.         while(::InternetReadFile(_hRequest
  496.                                  ,(LPVOID)(m_pData + m_dwContentSize)
  497.                                  ,dwPerRead
  498.                                  ,&dwReaded))
  499.         {
  500.             if(dwReaded == 0) break;
  501.             m_dwContentSize += dwReaded;
  502.             if(m_dwContentSize + dwPerRead > m_dwMaxSize)
  503.             {
  504.                 m_dwContentSize = m_dwMaxSize;
  505.                 break;
  506.             }
  507.             if(!InternetQueryDataAvailable(_hRequest
  508.                                    ,&dwPerRead
  509.                                    ,0
  510.                                    ,0))
  511.             {
  512.                 //等数据2秒,否则失败
  513.                 if(!WaitCompleteRequest(10*1000))
  514.                 {
  515.                     if(m_pCS)
  516.                     {
  517.                         PostMessage(m_pCS, WM_STATUS, ERR_INET_REQUEST_FAILED, 0);
  518.                     }
  519.                     //取消
  520.                     Cancel();
  521.                     goto DO_RELEASE;
  522.                 }
  523.             }
  524.             if(EnsureEnoughSpace(dwPerRead) == falsebreak;
  525.         }
  526.         m_uSeviceState = STATUS_FINISH;
  527.         //读取完成
  528.         if(m_pCS)
  529.         {
  530.             PostMessage(m_pCS, WM_RESPONSE, (WPARAM)m_pData, (LPARAM)m_dwContentSize);
  531.         }
  532. DO_RELEASE:
  533.         ;
  534.         //delete this;
  535. }
  536. //------------------------------------------------------------------------
  537. //状态回调函数
  538. //------------------------------------------------------------------------
  539. void CAsyncHttpClient::StatusCallback(HINTERNET hInternet,
  540.         DWORD_PTR dwContext,
  541.         DWORD dwInternetStatus,
  542.         LPVOID lpvStatusInformation,
  543.         DWORD dwStatusInformationLength)
  544. {
  545.     CAsyncHttpClient* pC = (CAsyncHttpClient*)dwContext;
  546.     switch (dwInternetStatus)
  547.     {   
  548.         case INTERNET_STATUS_HANDLE_CREATED:   //60
  549.             {
  550.                 INTERNET_ASYNC_RESULT* res = (INTERNET_ASYNC_RESULT*)lpvStatusInformation;
  551.                 pC->_hRequest = (HINTERNET)(res->dwResult);
  552.             }
  553.             break;
  554.         case INTERNET_STATUS_RESOLVING_NAME:   //10
  555.             {
  556.                 //AfxMessageBox(L"正在解析URL");
  557.             }
  558.             break;
  559.         case INTERNET_STATUS_NAME_RESOLVED:    //11
  560.             {
  561.                 //AfxMessageBox(L"URL已解析完毕");
  562.             }
  563.             break;
  564.         case INTERNET_STATUS_CONNECTING_TO_SERVER:   //20
  565.             {
  566.                 //AfxMessageBox(L"正在连接URL");
  567.             }
  568.             break;
  569.         case INTERNET_STATUS_CONNECTED_TO_SERVER:    //21
  570.             {
  571.                 //AfxMessageBox(L"已连接URL");
  572.             }
  573.             break;
  574.         case INTERNET_STATUS_SENDING_REQUEST:       //30
  575.             {
  576.                 //AfxMessageBox(L"正在发送请求");
  577.             }
  578.             break;
  579.         case INTERNET_STATUS_REQUEST_SENT:         //32
  580.             {
  581.                 //unsigned long *pnsent=(unsigned long*)lpvStatusInformation;
  582.                 //CString sz;
  583.                 //sz.Format(L"已发送%d字节", *pnsent);
  584.                 //AfxMessageBox(sz);
  585.                 
  586.             }
  587.             break;
  588.         case INTERNET_STATUS_RECEIVING_RESPONSE:  //40
  589.             {
  590.                 if(pC)
  591.                     pC->SetState(STATUS_BUSING);
  592.                 //AfxMessageBox(L"正在等待响应");
  593.             }
  594.             break;
  595.         case INTERNET_STATUS_RESPONSE_RECEIVED:  //41
  596.             {
  597.                 //AfxMessageBox(L"服务器已经响应");
  598.             }
  599.             break;
  600.         case INTERNET_STATUS_REQUEST_COMPLETE:   //100
  601.             {
  602.                 if(pC)
  603.                 {
  604.                     pC->SetCompleteRequest();       //请求完成
  605.                 }
  606.             }
  607.             break;
  608.         case INTERNET_STATUS_CLOSING_CONNECTION:  //50
  609.             {
  610.                 //AfxMessageBox(L"正在关闭连接");
  611.             }
  612.             break;
  613.         case INTERNET_STATUS_CONNECTION_CLOSED:  //51
  614.             {
  615.                 //AfxMessageBox(L"连接已关闭");
  616.             }
  617.             break;
  618.         case INTERNET_STATUS_HANDLE_CLOSING:   //70
  619.             break;
  620.         case INTERNET_STATUS_INTERMEDIATE_RESPONSE:  //120
  621.             break;
  622.         case INTERNET_STATUS_REDIRECT:   //110
  623.             break;
  624.         case INTERNET_STATUS_STATE_CHANGE:  //200
  625.             break;
  626.         default:
  627.             break;
  628.     };
  629.     return;
  630. }
  631. //数据读取例程
  632. DWORD CAsyncHttpClient::ThreadEntry(LPVOID pThis)
  633. {
  634.     ((CAsyncHttpClient*) pThis)->OnWork();
  635.     return 0;
  636. }
  637. //------------------------------------------------------------------------
  638. //辅助
  639. //------------------------------------------------------------------------
  640. //判断内存是否足够,不足按指定的粒度分配
  641. bool CAsyncHttpClient::EnsureEnoughSpace(DWORD dwRequired /*= 0*/)
  642. {
  643.     DWORD dwTotalSize = 0;
  644.     //计算内存是否足够
  645.     if(m_dwCurSize - m_dwContentSize >= dwRequired)
  646.     {
  647.         return true;
  648.     }
  649.     else  
  650.     {
  651.         //是否超过总大小
  652.         if((m_dwContentSize + dwRequired) > m_dwMaxSize)
  653.         {
  654.             if(m_pCS)
  655.             {
  656.                 PostMessage(m_pCS, WM_STATUS, ERR_MEMORY_EXPRESS, 0);
  657.             }
  658.             return false;
  659.         }
  660.         //按粒度计算需要的内存大小
  661.         dwTotalSize = m_dwContentSize + dwRequired;
  662.         if(((m_dwContentSize % m_dwUnitSize) + dwRequired) != 0)
  663.         {
  664.             dwTotalSize += m_dwUnitSize;
  665.         }
  666.         if(dwTotalSize > m_dwMaxSize) dwTotalSize = m_dwMaxSize;
  667.     }
  668.     //否则要再增加内存
  669.     //if(_hHeap == NULL)
  670.     //{
  671.     //  //获取系统内存页大小
  672.     //  SYSTEM_INFO  Sysinfo;
  673.     //  GetSystemInfo(&Sysinfo);
  674.     //  //make a stack which can chang big
  675.     //  //alloct memory
  676.     //  _hHeap = HeapCreate(HEAP_NO_SERIALIZE, Sysinfo.dwPageSize, 0);
  677.     //  if(0 == _hHeap)
  678.     //  {
  679.     //      if(m_pCS)
  680.     //      {
  681.     //          PostMessage(m_pCS, WM_STATUS, ERR_MEMORY_HEAP_FAILED, 0);
  682.     //      }
  683.     //      return false;
  684.     //  }
  685.     //}
  686.     LPVOID pData = NULL;
  687.     try
  688.     {
  689.         if(m_pData == NULL) //第一次分配
  690.         {
  691.             //pData = ::HeapAlloc(_hHeap
  692.             //                        ,HEAP_ZERO_MEMORY
  693.             //                        ,dwTotalSize);
  694.             pData = new char[dwTotalSize];
  695.             if(pData == NULL)
  696.             {
  697.                 if(m_pCS)
  698.                 {
  699.                     PostMessage(m_pCS, WM_STATUS, ERR_MEMORY_HEAP_FAILED, 0);
  700.                 }
  701.                 return false;
  702.             }    
  703.             m_dwCurSize = dwTotalSize;
  704.         }else//重新分配
  705.             //pData = HeapReAlloc(_hHeap, HEAP_ZERO_MEMORY, (LPVOID)m_pData, dwTotalSize);
  706.             pData = new char[dwTotalSize];
  707.             if(pData == NULL)
  708.           {
  709.                 if(m_pCS)
  710.                 {
  711.                     PostMessage(m_pCS, WM_STATUS, ERR_MEMORY_HEAP_FAILED, 0);
  712.                 }
  713.                 return false;
  714.             }
  715.             memmove(pData, m_pData, m_dwContentSize);
  716.             delete[] m_pData;
  717.             m_dwCurSize = dwTotalSize;
  718.         }
  719.     }
  720.     catch(...)
  721.     {
  722.         return false;
  723.     }
  724.     m_pData = (char*)pData;
  725.     return true;
  726. }
  727. //释放内存资源
  728. void CAsyncHttpClient::ReleaseResource()
  729. {
  730.     SAFE_DELARRAY(m_pszHost);
  731.     SAFE_DELARRAY(m_pszProg);
  732.     //SAFE_DELARRAY(m_pData);
  733.     if(m_pData)
  734.     {
  735.         //ASSERT(_hHeap);
  736.         //BOOL bRet = ::HeapFree(_hHeap, HEAP_NO_SERIALIZE, (LPVOID)m_pData);
  737.         //ASSERT(bRet);
  738.         //bRet = HeapDestroy(_hHeap);
  739.         //ASSERT(bRet);
  740.         SAFE_DELARRAY(m_pData);
  741.         m_pData = NULL;
  742.         m_dwCurSize = 0;
  743.         m_dwContentSize = 0;
  744.     }
  745.     if(_hCompleteRequestEvent != INVALID_HANDLE_VALUE)
  746.     {
  747.         ::CloseHandle(_hCompleteRequestEvent);
  748.         _hCompleteRequestEvent = INVALID_HANDLE_VALUE;
  749.     }
  750. }
  751. //完成请求
  752. void CAsyncHttpClient::SetCompleteRequest()
  753. {
  754.     if(_hCompleteRequestEvent !=0 && _hCompleteRequestEvent != INVALID_HANDLE_VALUE)
  755.         ::SetEvent(_hCompleteRequestEvent); 
  756. }
  757. //等待完成请求
  758. bool CAsyncHttpClient::WaitCompleteRequest(unsigned long ntime/*=INFINITE*/)
  759. {
  760.     if(!_hCompleteRequestEvent || _hCompleteRequestEvent==INVALID_HANDLE_VALUE)
  761.         false;
  762.     return ::WaitForSingleObject(_hCompleteRequestEvent, ntime)==WAIT_OBJECT_0? true:false;
  763. }
  764. //状态机转换
  765. bool CAsyncHttpClient::SetState(short uState)
  766. {
  767.     //if(STATUS_LAZY == m_uSeviceState)
  768.     //{
  769.     //  if(uState == STATUS_OPENNED)
  770.     //  {
  771.     //      m_uSeviceState = uState;
  772.     //  }else{
  773.     //      return false;
  774.     //  }
  775.     //}
  776.     //else if(STATUS_OPENNED == m_uSeviceState)
  777.     //{
  778.     //  //if(uState == STATUS_OPENNED || uState == )
  779.     //}
  780.     m_uSeviceState = uState;
  781.     return true;
  782. }
  783. short CAsyncHttpClient::GetState()
  784. {
  785.     return m_uSeviceState;
  786. }
  787. void CAsyncHttpClient::SetProgress(int nStep)
  788. {
  789.     m_nPercents += nStep;
  790.     if(m_nPercents > 100)
  791.         m_nPercents = 100;
  792. }

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值