用惯了 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 = 15000, int threads = 20, char * 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 }

转载于:https://www.cnblogs.com/kylindai/archive/2011/05/22/2053173.html

基于 C++ POCO 库封装的异步多线程的 CHttpClient 类相关推荐

  1. POCO库 Foundation::Thread模块 多线程与线程池支持

    本节主要介绍Thread类和ThreadLocal机制的使用方法以及实现原理,以及对ThreadPool线程池支持的简单了解 在C++语言中,我们通过_beginThreadex或CreateThre ...

  2. 基于 Multitype 开源库封装更好用的RecyclerView.Adapter

    前言 MultiType 这个项目,至今 v3.x 稳定多时,考虑得非常多,但也做得非常克制.原则一直是 直观.灵活.可靠.简单纯粹(其中直观和灵活是非常看重的). 这是 MultiType 框架作者 ...

  3. C++ POCO库(访问数据库,版本问题,本人配置失败)

    官网下载源码:https://pocoproject.org/ 一.POCO库简介 学习一个框架前,要先明白它的是什么,为什么,怎么用.下面这些文字,是从中文poco官网上转过来的,正如poco c+ ...

  4. libcurl开源库封装ftp工具,支持多线程并发、断点续传、超时连接、传输速率控制

    各位朋友好,第一次在CSDN写博客,后续时间充足的话会陆续更新一些资源,大家一起探讨交流,感谢!!! 如有任何疑问,可以留言. 目的:再次封装CURL接口,使用FTP相关接口更方便,更易懂 功能: 可 ...

  5. Android 基于 Speex 的高度封装语音库,0 耦合,没三方jar包

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...

  6. 基于纤程(Fiber)实现C++异步编程库(一):原理及示例

    纤程(Fiber)和协程(coroutine)是差不多的概念,也叫做用户级线程或者轻线程之类的.Windows系统提供了一组API用户创建和使用纤程,本文中的库就是基于这组API实现的,所以无法跨平台 ...

  7. dio设置自定义post请求_基于dio库封装flutter项目的标准网络框架

    网络框架是每个应用的基石,封装一个好的网络框架不仅是项目的一个好的开始,并且直接影响到随后项目的稳定性和可扩展性.在移动开发的各个端都有非常赞的网络请求基础框架,比如Android的okhttp库.s ...

  8. 基于猿题库网络请求再次封装

    下载地址:  https://github.com/weibo1314/WB_NeiApiManager WB_NetApiManager 介绍 ===================== 最近闲来无 ...

  9. 异步多线程之入门必知

    下一篇:异步多线程之入Thread 简介 今天来谈谈异步多线程,做网站服务的同学都知道,Web 应用是天生的异步多线程,无论做 Winform.WPF.Webform 等,异步多线程的应用是非常广泛的 ...

最新文章

  1. Mac OSX 10.9下apache+php+mysql的配置
  2. 回溯法模板(矩阵中操作)
  3. c语言主范式与编码,超详细!终于搞明白KMP算法
  4. Python面向对象-概念、类、实例
  5. 寄存器分配图着色_【02】从零开始的卡通渲染-着色篇1
  6. 荷兰商业银行使用精益领导力推行改进
  7. python 网络渗透_python 网络编程(渗透与编程一)
  8. selenium课程笔记3-使用selenium中的webdriver对浏览器操作-页面元素定位及操作
  9. (一)Nand FLASH 原理讲解
  10. Win10 配置 Python 环境变量
  11. php 查询access数据库操作,php操作access数据库的方法详解
  12. 《算法图解》笔记与总结
  13. 课设-基于51单片机+超声波模块的避障小车(源码+原理图+Protel仿真)
  14. vbs整人代码大集合(多年以来的整合)
  15. 使用exe4j打包Java桌面程序为exe
  16. 表头顺序不一样的表格如何合并_不同表头的多表合并
  17. 面试总结——百度校招二面跪了
  18. 三星“太子”李在镕加入三星电子董事会
  19. android 3d魔方 代码,3D魔方 - android代码库 - 云代码
  20. Exadata 机器介绍

热门文章

  1. win10玩cf不能全屏_游戏莫名卡顿三招搞定!Win10游戏优化教程
  2. python正则表达式代码_python正则表达式的使用(实验代码)
  3. html跨域post请求,使用fetch跨域POST请求
  4. SpringClound介绍
  5. MATLAB基础学习笔记01:初探MATLAB世界
  6. Python编程基础17:构造方法和析构方法
  7. 鸿蒙应用案例:Ability应用与管理
  8. 16.对极几何——极线约束,收敛相机,平行图像平面,两个立体对 测验_2
  9. noip2016的研究
  10. python中xlrd.open_workbook_python解决open()函数、xlrd.open_workbook()函数文件名包含中文,sheet名包含中文报错的问题...