基于 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);
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
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
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
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
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 类相关推荐
- POCO库 Foundation::Thread模块 多线程与线程池支持
本节主要介绍Thread类和ThreadLocal机制的使用方法以及实现原理,以及对ThreadPool线程池支持的简单了解 在C++语言中,我们通过_beginThreadex或CreateThre ...
- 基于 Multitype 开源库封装更好用的RecyclerView.Adapter
前言 MultiType 这个项目,至今 v3.x 稳定多时,考虑得非常多,但也做得非常克制.原则一直是 直观.灵活.可靠.简单纯粹(其中直观和灵活是非常看重的). 这是 MultiType 框架作者 ...
- C++ POCO库(访问数据库,版本问题,本人配置失败)
官网下载源码:https://pocoproject.org/ 一.POCO库简介 学习一个框架前,要先明白它的是什么,为什么,怎么用.下面这些文字,是从中文poco官网上转过来的,正如poco c+ ...
- libcurl开源库封装ftp工具,支持多线程并发、断点续传、超时连接、传输速率控制
各位朋友好,第一次在CSDN写博客,后续时间充足的话会陆续更新一些资源,大家一起探讨交流,感谢!!! 如有任何疑问,可以留言. 目的:再次封装CURL接口,使用FTP相关接口更方便,更易懂 功能: 可 ...
- Android 基于 Speex 的高度封装语音库,0 耦合,没三方jar包
作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...
- 基于纤程(Fiber)实现C++异步编程库(一):原理及示例
纤程(Fiber)和协程(coroutine)是差不多的概念,也叫做用户级线程或者轻线程之类的.Windows系统提供了一组API用户创建和使用纤程,本文中的库就是基于这组API实现的,所以无法跨平台 ...
- dio设置自定义post请求_基于dio库封装flutter项目的标准网络框架
网络框架是每个应用的基石,封装一个好的网络框架不仅是项目的一个好的开始,并且直接影响到随后项目的稳定性和可扩展性.在移动开发的各个端都有非常赞的网络请求基础框架,比如Android的okhttp库.s ...
- 基于猿题库网络请求再次封装
下载地址: https://github.com/weibo1314/WB_NeiApiManager WB_NetApiManager 介绍 ===================== 最近闲来无 ...
- 异步多线程之入门必知
下一篇:异步多线程之入Thread 简介 今天来谈谈异步多线程,做网站服务的同学都知道,Web 应用是天生的异步多线程,无论做 Winform.WPF.Webform 等,异步多线程的应用是非常广泛的 ...
最新文章
- Mac OSX 10.9下apache+php+mysql的配置
- 回溯法模板(矩阵中操作)
- c语言主范式与编码,超详细!终于搞明白KMP算法
- Python面向对象-概念、类、实例
- 寄存器分配图着色_【02】从零开始的卡通渲染-着色篇1
- 荷兰商业银行使用精益领导力推行改进
- python 网络渗透_python 网络编程(渗透与编程一)
- selenium课程笔记3-使用selenium中的webdriver对浏览器操作-页面元素定位及操作
- (一)Nand FLASH 原理讲解
- Win10 配置 Python 环境变量
- php 查询access数据库操作,php操作access数据库的方法详解
- 《算法图解》笔记与总结
- 课设-基于51单片机+超声波模块的避障小车(源码+原理图+Protel仿真)
- vbs整人代码大集合(多年以来的整合)
- 使用exe4j打包Java桌面程序为exe
- 表头顺序不一样的表格如何合并_不同表头的多表合并
- 面试总结——百度校招二面跪了
- 三星“太子”李在镕加入三星电子董事会
- android 3d魔方 代码,3D魔方 - android代码库 - 云代码
- Exadata 机器介绍
热门文章
- win10玩cf不能全屏_游戏莫名卡顿三招搞定!Win10游戏优化教程
- python正则表达式代码_python正则表达式的使用(实验代码)
- html跨域post请求,使用fetch跨域POST请求
- SpringClound介绍
- MATLAB基础学习笔记01:初探MATLAB世界
- Python编程基础17:构造方法和析构方法
- 鸿蒙应用案例:Ability应用与管理
- 16.对极几何——极线约束,收敛相机,平行图像平面,两个立体对 测验_2
- noip2016的研究
- python中xlrd.open_workbook_python解决open()函数、xlrd.open_workbook()函数文件名包含中文,sheet名包含中文报错的问题...