异步多线程,基于 C++ POCO 1.4.1 库 封装的异步多线程的 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);
/**
* 为HttpExchange 设置 Handler 处理回调类,以后具体的逻辑由 CHttpHandler 继承的具体业务处理逻辑类完成。
* pHandler CHttpHandler HTTP 事件处理类
*/
CHttpExchange.SetHandler(CHttpHandler * pHandler);
/**
* 当收到响应完成时的事件回调函数,传入 HttpStatus 和 文本的Response,
* 目前仅支持文本 Response,即:Resonse.getContentType() 为 text 类型
*/
CHttpHandler.OnResponseComplate(HTTPResponse::HTTPStatus status, const string& responseContent);
(一)CHttpClient CHttpExchange CHttpHandler 类图:
(二)代码:
HttpClient.h
异步多线程,基于 C++ POCO 1.4.1 库 封装的异步多线程的 CHttpClient 类异步多线程,基于 C++ POCO 1.4.1 库 封装的异步多线程的 CHttpClient 类View Code 1 ////////////////////////////////////////////////////////////////////////// 2 // HttpClient.h 3 // Author: Kylin.dai @kylindai 4 // Date: 2011-05-21 5 ////////////////////////////////////////////////////////////////////////// 6 7 #pragma _disibledevent=> 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 28 #include 29 #include 30 #include 31 #include 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 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 _disibledevent=> 57 virtual void _disibledevent=> 58 virtual void _disibledevent=> 59 virtual void _disibledevent=>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 = 15000, int threads = 20, char * pLogFileName = NULL); 134 void Start(); 135 void Stop(); 136 void Send(CHttpExchange * pExchange); 137 };

HttpClient.cpp
View Code 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 }

Tags:  异步多线程

延伸阅读

最新评论

发表评论