zoukankan      html  css  js  c++  java
  • 基于 C++ POCO 库封装的异步多线程的 CHttpClient 类

    用惯了 Jetty 的 基于事件的 HttpClient 类,在C++平台上也没找到这样调用方式的类库,只好自己写一个了。

    目前版本 1.0,朋友们看了给点建议。(注:Kylindai原创,转载请注明出处)

    Feature: 基于C++跨平台的 POCO 库实现,支持线程池 Poco::ThreadPool, 异步 HttpClient, 支持Http事件回调处理。

    基本思路,核心方法:

    /**

     * 创建多线程支持的HttpClient,

     * nTimeout 超时

     * nMaxThreads 最大线程数

     * pLogFileName 日志文件

     */

    CHttpClient.Create(int nTimeout, int nMaxThreads, char * pLogFileName = NULL);

    /**

     * 发送请求,此方法会创建一个 CHttpTask 放到线程池里,然后由线程发起 HTTPClientSession 请求,

     * 收到响应后,回调 CHttpExchange.GetHandler().OnResponseComplate() 方法。

     * 类似 Java Jetty的 HttpClient.send(HttpExchange exchange)

     * pExchange CHttpExchange HTTP 交换类

     */

    CHttpClient.Send(CHttpExchange * pExchange); 

     1 void CHttpClient::Send(CHttpExchange * pExchange)
     2 {
     3     try 
     4     {
     5         CHttpTask * pHttpTask = new CHttpTask(pExchange, m_timeout, m_pLogger);
     6         ThreadPool::defaultPool().start(* pHttpTask);
     7     } 
     8     catch (Exception& ex)
     9     {
    10         if (m_pLogger != NULL)
    11         {
    12             m_pLogger->error(ex.displayText());
    13         }
    14     }
    15 }

    /**

     * 线程池中任务 CHttpTask.run 处理Http请求及响应

     */

    CHttpTask : public Runnable

     1 void CHttpTask::run()
     2 {
     3     CHttpHandler * pHandler = m_pExchange->GetHandler();
     4 
     5     try
     6     {
     7         HTTPClientSession httpClientSession;
     8         httpClientSession.setHost(m_pExchange->GetHost());
     9         httpClientSession.setTimeout(m_timeout);
    10         httpClientSession.sendRequest(m_pExchange->GetHttpRequest());
    11 
    12         HTTPResponse response;
    13         istream& rs = httpClientSession.receiveResponse(response);
    14 
    15         if (pHandler != NULL)
    16         {
    17             const string& contentType = response.getContentType();
    18             if (contentType.find("text/">= 0)
    19             {
    20                 stringstream responseStream;
    21                 StreamCopier::copyStream(rs, responseStream);
    22 
    23                 string responseContent;
    24                 responseStream >> responseContent;
    25 
    26                 pHandler->OnResponseComplete(response.getStatus(), responseContent);
    27             }
    28         }
    29     }
    30     catch (Exception& ex)
    31     {
    32         if (m_pLogger != NULL)
    33         {
    34             m_pLogger->error(ex.displayText());
    35         }
    36     }
    37 
    38     if (pHandler != NULL)
    39     {
    40         delete pHandler;
    41     }
    42 
    43     delete this;
    44 }

    /**

     * 为HttpExchange 设置 Handler 处理回调类,以后具体的逻辑由 CHttpHandler 继承的具体业务处理逻辑类完成。

     * pHandler CHttpHandler HTTP 事件处理类

     */

    CHttpExchange.SetHandler(CHttpHandler * pHandler);

    /**

     * 当收到响应完成时的事件回调函数,传入 HttpStatus 和 文本的Response,

     * 目前仅支持文本 Response,即:Resonse.getContentType() 为 text 类型

     */

    CHttpHandler.OnResponseComplate(HTTPResponse::HTTPStatus status, const string& responseContent);

    CCheckVersionHandler : public CHttpHandler

     1 void CCheckVersionHandler::OnResponseComplete(HTTPResponse::HTTPStatus status, const string& responseContent)
     2 {
     3     CHttpHandler::OnResponseComplete(status, responseContent);
     4 
     5     if (status == HTTPResponse::HTTP_OK)
     6     {
     7         const string& version = responseContent;
     8 
     9         m_pMainWnd->ShowVersionMessage(version);
    10     }
    11 }

    (一)CHttpClient CHttpExchange CHttpHandler 类图:

    (二)代码:

    HttpClient.h

      1 //////////////////////////////////////////////////////////////////////////
      2 //  HttpClient.h
      3 //  Author: Kylin.dai @kylindai
      4 //  Date: 2011-05-21
      5 //////////////////////////////////////////////////////////////////////////
      6 
      7 #pragma once
      8 
      9 #include "Poco/AutoPtr.h"
     10 #include "Poco/Logger.h"
     11 #include "Poco/PatternFormatter.h"
     12 #include "Poco/FormattingChannel.h"
     13 #include "Poco/ConsoleChannel.h"
     14 #include "Poco/FileChannel.h"
     15 #include "Poco/Message.h"
     16 #include "Poco/Exception.h"
     17 #include "Poco/StreamCopier.h"
     18 #include "Poco/ThreadPool.h"
     19 #include "Poco/Thread.h"
     20 #include "Poco/Mutex.h"
     21 #include "Poco/Runnable.h"
     22 #include "Poco/Stopwatch.h"
     23 #include "Poco/Net/HTTPClientSession.h"
     24 #include "Poco/Net/HTTPRequest.h"
     25 #include "Poco/Net/HTTPResponse.h"
     26 
     27 #include <string>
     28 #include <iostream>
     29 #include <sstream>
     30 #include <fstream>
     31 #include <map>
     32 
     33 using namespace std;
     34 using namespace Poco;
     35 using namespace Poco::Net;
     36 
     37 //////////////////////////////////////////////////////////////////////////
     38 // CHttpHandler Class
     39 //////////////////////////////////////////////////////////////////////////
     40 class CHttpHandler
     41 {
     42 public:
     43     CHttpHandler(char * pLogFileName = NULL);
     44     ~CHttpHandler();
     45 
     46 private:
     47     map<const string, LPVOID> m_attributeMap;
     48 
     49 protected:
     50     Logger * m_pLogger;
     51 
     52 public:
     53     void SetAttribute(const string& name, LPVOID value);
     54     LPVOID GetAttribute(const string& name);
     55 
     56     virtual void OnException();
     57     virtual void OnExpire();
     58     virtual void OnRequestComplete();
     59     virtual void OnResponseComplete(HTTPResponse::HTTPStatus status, const string& responseContent);
     60 };
     61 
     62 //////////////////////////////////////////////////////////////////////////
     63 // CHttpExchange Class
     64 //////////////////////////////////////////////////////////////////////////
     65 class CHttpExchange
     66 {
     67 public:
     68     CHttpExchange();
     69     ~CHttpExchange();
     70 
     71 private:
     72     int m_timeout;
     73     HTTPRequest * m_pRequest;
     74     CHttpHandler * m_pHandler;
     75 
     76 public:
     77     HTTPRequest& GetHttpRequest();
     78 
     79     void SetMethod(const string& strMethod);
     80     const string& GetMethod() const;
     81 
     82     void SetContentType(const string& strContentType);
     83     const string& GetContentType() const;
     84 
     85     void SetHost(const string& strHost);
     86     const string& GetHost() const;
     87 
     88     void SetUri(const string& strUri);
     89     const string& GetUri() const;
     90 
     91     void SetHandler(CHttpHandler * pHandler);
     92     CHttpHandler * GetHandler();
     93 };
     94 
     95 //////////////////////////////////////////////////////////////////////////
     96 // CHttpTask Class
     97 //////////////////////////////////////////////////////////////////////////
     98 class CHttpTask : public Runnable
     99 {
    100 public:
    101     CHttpTask(CHttpExchange * pExchange, int timeout = 15000, Logger * pLogger = NULL);
    102     ~CHttpTask();
    103 
    104 private:
    105     CHttpExchange * m_pExchange;
    106     int m_timeout;
    107 
    108 protected:
    109     Logger * m_pLogger;
    110 
    111 public:
    112     void run();
    113 };
    114 
    115 //////////////////////////////////////////////////////////////////////////
    116 // CHttpClient Class
    117 //////////////////////////////////////////////////////////////////////////
    118 class CHttpClient
    119 {
    120 public:
    121     CHttpClient();
    122     ~CHttpClient();
    123 
    124 private:
    125     int m_timeout;
    126     int m_threads;
    127     char * m_pLogFileName;
    128 
    129 protected:
    130     Logger * m_pLogger;
    131 
    132 public:
    133     void Create(int timeout = 15000int threads = 20char * pLogFileName = NULL);
    134     void Start();
    135     void Stop();
    136     void Send(CHttpExchange * pExchange);
    137 };

    HttpClient.cpp

      1 //////////////////////////////////////////////////////////////////////////
      2 //  HttpClient.cpp
      3 //  Author: Kylin.dai @kylindai
      4 //  Date: 2011-05-21
      5 //////////////////////////////////////////////////////////////////////////
      6 
      7 #include "HttpClient.h"
      8 
      9 //////////////////////////////////////////////////////////////////////////
     10 // CHttpHandler Methods
     11 //////////////////////////////////////////////////////////////////////////
     12 CHttpHandler::CHttpHandler(char * pLogFileName)
     13 {
     14     m_pLogger = NULL;
     15 
     16     // create logger
     17     if (pLogFileName != NULL) 
     18     {
     19         try
     20         {
     21             string logFileName(pLogFileName);
     22 
     23             FormattingChannel* pFCFile = new FormattingChannel(new PatternFormatter("%Y-%m-%d %H:%M:%S.%c %N[%P]:%s:%q:%t"));
     24             pFCFile->setChannel(new FileChannel(logFileName));
     25             pFCFile->open();
     26 
     27             m_pLogger = & Logger::create("HttpHandler", pFCFile, Message::PRIO_DEBUG); //Message::PRIO_WARNING);
     28         }
     29         catch (Exception& ex)
     30         {
     31         }
     32     } 
     33 }
     34 
     35 CHttpHandler::~CHttpHandler()
     36 {
     37     if (m_pLogger != NULL)
     38     {
     39         m_pLogger->getChannel()->close();
     40     }
     41 }
     42 
     43 void CHttpHandler::SetAttribute(const string& name, LPVOID value)
     44 {
     45     m_attributeMap[name] = value;
     46 }
     47 
     48 LPVOID CHttpHandler::GetAttribute(const string& name)
     49 {
     50     return m_attributeMap[name];
     51 }
     52 
     53 void CHttpHandler::OnException()
     54 {
     55 
     56 }
     57 
     58 void CHttpHandler::OnExpire()
     59 {
     60 
     61 }
     62 
     63 void CHttpHandler::OnRequestComplete()
     64 {
     65 
     66 }
     67 
     68 void CHttpHandler::OnResponseComplete(HTTPResponse::HTTPStatus status, const string& responseContent)
     69 {
     70     if (m_pLogger != NULL)
     71     {
     72         stringstream messageStream;
     73         messageStream << "HTTP STATUS:" << status << " : " << responseContent << endl;
     74 
     75         m_pLogger->debug(messageStream.str());
     76     }
     77 }
     78 
     79 //////////////////////////////////////////////////////////////////////////
     80 // CHttpExchange Methods
     81 //////////////////////////////////////////////////////////////////////////
     82 CHttpExchange::CHttpExchange() 
     83 {
     84     m_pRequest = new HTTPRequest();
     85     m_pRequest->setVersion(HTTPRequest::HTTP_1_1);
     86 }
     87 
     88 CHttpExchange::~CHttpExchange()
     89 {
     90     if (m_pRequest != NULL)
     91     {
     92 //        delete m_pRequest;
     93     }
     94 }
     95 
     96 HTTPRequest& CHttpExchange::GetHttpRequest()
     97 {
     98     return * m_pRequest;
     99 }
    100 
    101 void CHttpExchange::SetMethod(const string& strMethod)
    102 {
    103     m_pRequest->setMethod(strMethod);
    104 }
    105 
    106 const string& CHttpExchange::GetMethod() const
    107 {
    108     return m_pRequest->getMethod();
    109 }
    110 
    111 void CHttpExchange::SetContentType(const string& strContentType)
    112 {
    113     m_pRequest->setContentType(strContentType);
    114 }
    115 
    116 const string& CHttpExchange::GetContentType() const
    117 {
    118     return m_pRequest->getContentType();
    119 }
    120 
    121 void CHttpExchange::SetHost(const string& strHost)
    122 {
    123     m_pRequest->setHost(strHost);
    124 }
    125 
    126 const string& CHttpExchange::GetHost() const
    127 {
    128     return m_pRequest->getHost();
    129 }
    130 
    131 void CHttpExchange::SetUri(const string& strUri)
    132 {
    133     m_pRequest->setURI(strUri);
    134 }
    135 
    136 const string& CHttpExchange::GetUri() const
    137 {
    138     return m_pRequest->getURI();
    139 }
    140 
    141 void CHttpExchange::SetHandler(CHttpHandler * pHandler)
    142 {
    143     m_pHandler = pHandler;
    144 }
    145 
    146 CHttpHandler * CHttpExchange::GetHandler()
    147 {
    148     return m_pHandler;
    149 }
    150 
    151 //////////////////////////////////////////////////////////////////////////
    152 // CHttpTask Methods
    153 //////////////////////////////////////////////////////////////////////////
    154 CHttpTask::CHttpTask(CHttpExchange * pExchange, int timeout, Logger * pLogger):
    155     m_pExchange(pExchange),
    156     m_timeout(timeout),
    157     m_pLogger(pLogger)
    158 {
    159     
    160 }
    161 
    162 CHttpTask::~CHttpTask()
    163 {
    164     if (m_pExchange != NULL)
    165     {
    166         delete m_pExchange;
    167     }
    168 }
    169 
    170 void CHttpTask::run()
    171 {
    172     CHttpHandler * pHandler = m_pExchange->GetHandler();
    173 
    174     try
    175     {
    176         HTTPClientSession httpClientSession;
    177         httpClientSession.setHost(m_pExchange->GetHost());
    178         httpClientSession.setTimeout(m_timeout);
    179         httpClientSession.sendRequest(m_pExchange->GetHttpRequest());
    180 
    181         HTTPResponse response;
    182         istream& rs = httpClientSession.receiveResponse(response);
    183 
    184         if (pHandler != NULL)
    185         {
    186             const string& contentType = response.getContentType();
    187             if (contentType.find("text/">= 0)
    188             {
    189                 stringstream responseStream;
    190                 StreamCopier::copyStream(rs, responseStream);
    191 
    192                 string responseContent;
    193                 responseStream >> responseContent;
    194 
    195                 pHandler->OnResponseComplete(response.getStatus(), responseContent);
    196             }
    197         }
    198     }
    199     catch (Exception& ex)
    200     {
    201         if (m_pLogger != NULL)
    202         {
    203             m_pLogger->error(ex.displayText());
    204         }
    205     }
    206 
    207     if (pHandler != NULL)
    208     {
    209         delete pHandler;
    210     }
    211 
    212     delete this;
    213 }
    214 
    215 //////////////////////////////////////////////////////////////////////////
    216 // CHttpClient Methods
    217 //////////////////////////////////////////////////////////////////////////
    218 CHttpClient::CHttpClient()
    219 {
    220     m_pLogger = NULL;
    221 }
    222 
    223 CHttpClient::~CHttpClient()
    224 {
    225     if (m_pLogger != NULL)
    226     {
    227         m_pLogger->getChannel()->close();
    228     }
    229 }
    230 
    231 void CHttpClient::Create(int timeout, int threads, char * pLogFileName)
    232 {
    233     m_timeout = timeout;
    234     m_threads = threads;
    235     m_pLogFileName = pLogFileName;
    236 
    237     ThreadPool::defaultPool().addCapacity(threads);
    238 
    239     // create logger
    240     if (pLogFileName != NULL) 
    241     {
    242         try
    243         {
    244             string logFileName(pLogFileName);
    245 
    246             FormattingChannel* pFCFile = new FormattingChannel(new PatternFormatter("%Y-%m-%d %H:%M:%S.%c %N[%P]:%s:%q:%t"));
    247             pFCFile->setChannel(new FileChannel(logFileName));
    248             pFCFile->open();
    249 
    250             m_pLogger = & Logger::create("fileLogger", pFCFile, Message::PRIO_WARNING);
    251         }
    252         catch (Exception& ex)
    253         {
    254         }
    255     } 
    256     /*
    257     else 
    258     {
    259         FormattingChannel* pFCConsole = new FormattingChannel(new PatternFormatter("%s: %p: %t"));
    260         pFCConsole->setChannel(new ConsoleChannel);
    261         pFCConsole->open();
    262 
    263         m_pLogger = & Logger::create("ConsoleLogger", pFCConsole, Message::PRIO_DEBUG);
    264     }
    265     */
    266 }
    267 
    268 void CHttpClient::Start()
    269 {
    270 
    271 }
    272 
    273 void CHttpClient::Stop()
    274 {
    275 //    ThreadPool::defaultPool().joinAll();
    276 }
    277 
    278 void CHttpClient::Send(CHttpExchange * pExchange)
    279 {
    280     try 
    281     {
    282         CHttpTask * pHttpTask = new CHttpTask(pExchange, m_timeout, m_pLogger);
    283         ThreadPool::defaultPool().start(* pHttpTask);
    284     } 
    285     catch (Exception& ex)
    286     {
    287         if (m_pLogger != NULL)
    288         {
    289             m_pLogger->error(ex.displayText());
    290         }
    291     }
    292 }
  • 相关阅读:
    c++中stl函数的使用
    java 中String类的常见方法和StringBuffer类的使用
    c++模板类和模板函数
    c++简单工厂类的设计模式
    Android自定义的button按钮
    c++基类与派生类之间的转换
    Unity和Android结合出现Unabled to convert class into dex format
    jz2240用tftp下载程序步骤
    解决jz2440不能ping同主机问题
    android中的事件传递机制
  • 原文地址:https://www.cnblogs.com/kylindai/p/2053173.html
Copyright © 2011-2022 走看看