tc_http_async.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /**
  2. * Tencent is pleased to support the open source community by making Tars available.
  3. *
  4. * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
  5. *
  6. * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  7. * in compliance with the License. You may obtain a copy of the License at
  8. *
  9. * https://opensource.org/licenses/BSD-3-Clause
  10. *
  11. * Unless required by applicable law or agreed to in writing, software distributed
  12. * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  13. * CONDITIONS OF ANY KIND, either express or implied. See the License for the
  14. * specific language governing permissions and limitations under the License.
  15. */
  16. #ifndef __TC_HTTP_ASYNC_H_
  17. #define __TC_HTTP_ASYNC_H_
  18. #include <functional>
  19. #include "util/tc_platform.h"
  20. #include "util/tc_thread_pool.h"
  21. #include "util/tc_network_buffer.h"
  22. #include "util/tc_http.h"
  23. #include "util/tc_autoptr.h"
  24. #include "util/tc_socket.h"
  25. namespace tars
  26. {
  27. /////////////////////////////////////////////////
  28. /**
  29. * @file tc_http_async.h
  30. * @brief http异步调用类.
  31. *
  32. * http同步调用使用TC_HttpRequest::doRequest就可以了
  33. * 代码示例请参考example_http_async.cpp
  34. * 说明:
  35. * 1 背后会启动唯一的网络线程
  36. * 2 目前只支持http短连接
  37. * 3 RequestCallback回调里面, onSucc和onFailed是对应的, 每次异步请求, onSucc/onFailed其中之一会被唯一响应
  38. * @author ruanshudong@qq.com
  39. */
  40. /////////////////////////////////////////////////
  41. /**
  42. * @brief 异步线程处理类.
  43. */
  44. class TC_HttpAsync : public TC_Thread, public TC_ThreadLock
  45. {
  46. public:
  47. /**
  48. * @brief 异步请求回调对象
  49. * onSucc, 收到成功回包时响应
  50. * onFailed, 失败时响应
  51. * onSucc和onFailed是成对出现的, 且一次请求, 只会一个被响应, 且只响应一次
  52. * onFailed被调用时, 链接就会被关闭掉
  53. */
  54. class RequestCallback : public TC_HandleBase
  55. {
  56. public:
  57. /**
  58. * 错误码
  59. */
  60. enum FAILED_CODE
  61. {
  62. Failed_Net = 0x01, //网络出错
  63. Failed_Connect = 0x02, //连接服务器出错
  64. Failed_Timeout = 0x03, //超时
  65. Failed_Interrupt = 0x04, //中断接收数据
  66. Failed_Close = 0x05, //服务器主动关闭了链接
  67. Failed_ConnectTimeout = 0x06, //链接超时
  68. };
  69. /**
  70. * @brief 每次收到数据且http头收全了都会调用,
  71. * stHttpResponse的数据可能不是完全的http响应数据 ,只有部分body数据
  72. * @param stHttpResponse 收到的http数据
  73. * @return true:继续收取数据, false:不收取数据了(会触发onFailed, Failed_Interrupt)
  74. */
  75. virtual bool onContinue(TC_HttpResponse &stHttpResponse) { return true; }
  76. /**
  77. * @brief 完整的响应回来了.
  78. *
  79. * @param stHttpResponse http响应包
  80. */
  81. virtual void onSucc(TC_HttpResponse &stHttpResponse) = 0;
  82. /**
  83. * @brief 异常, 发生异常时, onClose也会被调用, 连接会被关闭掉
  84. *
  85. * @param ret, 错误码
  86. * @param info 异常原因
  87. */
  88. virtual void onFailed(FAILED_CODE ret, const string &info) = 0;
  89. /**
  90. * @brief 连接被关闭
  91. */
  92. virtual void onClose() {};
  93. };
  94. typedef TC_AutoPtr<RequestCallback> RequestCallbackPtr;
  95. protected:
  96. /**
  97. * @brief 异步http请求(短连接)
  98. */
  99. class AsyncRequest : public TC_HandleBase
  100. {
  101. public:
  102. /**
  103. * @brief 构造.
  104. *
  105. * @param stHttpRequest
  106. * @param callbackPtr
  107. */
  108. AsyncRequest(TC_HttpRequest &stHttpRequest, RequestCallbackPtr &callbackPtr, bool bUseProxy);
  109. /**
  110. * @brief 构造.
  111. *
  112. * @param stHttpRequest
  113. * @param callbackPtr
  114. * @param addr
  115. */
  116. AsyncRequest(TC_HttpRequest &stHttpRequest, RequestCallbackPtr &callbackPtr, const string &addr);
  117. /**
  118. * @brief 析构
  119. */
  120. ~AsyncRequest();
  121. /**
  122. * @brief 获取句柄
  123. *
  124. * @return int
  125. */
  126. int getfd() const { return _fd.getfd(); }
  127. /**
  128. * @brief 发起建立连接.
  129. *
  130. */
  131. void doConnect();
  132. /**
  133. * @brief 获取系统错误提示
  134. * @return
  135. */
  136. string getError(const string &sDefault) const;
  137. /**
  138. * @brief 发生异常
  139. */
  140. void doException(RequestCallback::FAILED_CODE ret, const string &e);
  141. /**
  142. * @brief 发送请求
  143. */
  144. void doRequest();
  145. /**
  146. * @brief 接收响应
  147. */
  148. void doReceive();
  149. /**
  150. * @brief 关闭连接
  151. */
  152. void doClose();
  153. /**
  154. * @brief 超时
  155. */
  156. void timeout();
  157. /**
  158. * @brief 设置唯一ID.
  159. *
  160. * @param uniqId
  161. */
  162. void setUniqId(uint32_t uniqId) { _iUniqId = uniqId;}
  163. /**
  164. * @brief 获取唯一ID.
  165. *
  166. * @return uint32_t
  167. */
  168. uint32_t getUniqId() const { return _iUniqId; }
  169. /**
  170. * @brief 设置处理请求的http异步线程.
  171. *
  172. * @param pHttpAsync :异步线程处理对象
  173. */
  174. void setHttpAsync(TC_HttpAsync *pHttpAsync) { _pHttpAsync = pHttpAsync; }
  175. /**
  176. * @brief 设置发网络请求时绑定的ip地址.
  177. *
  178. * @param addr
  179. */
  180. void setBindAddr(const struct sockaddr* addr);
  181. /**
  182. * @brief 链接是否有效
  183. */
  184. bool isValid() const { return _fd.isValid(); }
  185. /**
  186. * @brief 是否链接上
  187. * @return [description]
  188. */
  189. bool hasConnected() const { return _isConnected; }
  190. /**
  191. * @brief 设置链接状态
  192. * @param isConnected [description]
  193. */
  194. void setConnected(bool isConnected) { _isConnected = isConnected; }
  195. /**
  196. * 处理网络事件
  197. * @param events [description]
  198. */
  199. void processNet(const epoll_event &ev);
  200. /**
  201. * 处理通知事件
  202. */
  203. void processNotify();
  204. protected:
  205. /**
  206. * @brief 接收请求.
  207. *
  208. * @param buf
  209. * @param len
  210. * @param flag
  211. * @return int
  212. */
  213. int recv(void* buf, uint32_t len, uint32_t flag);
  214. /**
  215. * @brief 发送请求.
  216. *
  217. * @param buf 发送内容
  218. * @param len 发送长度
  219. * @param flag
  220. * @return int
  221. */
  222. int send(const void* buf, uint32_t len, uint32_t flag);
  223. protected:
  224. TC_HttpAsync *_pHttpAsync;
  225. TC_HttpResponse _stHttpResp;
  226. TC_Socket _fd;
  227. string _sHost;
  228. uint32_t _iPort;
  229. uint32_t _iUniqId;
  230. TC_NetWorkBuffer _sendBuffer;
  231. TC_NetWorkBuffer _recvBuffer;
  232. RequestCallbackPtr _callbackPtr;
  233. bool _bindAddrSet;
  234. struct sockaddr _bindAddr;
  235. bool _bUseProxy;
  236. bool _isConnected;
  237. };
  238. typedef TC_AutoPtr<AsyncRequest> AsyncRequestPtr;
  239. public:
  240. typedef TC_TimeoutQueue<AsyncRequestPtr> http_queue_type;
  241. /**
  242. * @brief 构造函数
  243. */
  244. TC_HttpAsync();
  245. /**
  246. * @brief 析构函数
  247. */
  248. ~TC_HttpAsync();
  249. /**
  250. * @brief 异步发起请求.
  251. *
  252. * @param stHttpRequest
  253. * @param httpCallbackPtr
  254. * @param bUseProxy,是否使用代理方式连接
  255. */
  256. void doAsyncRequest(TC_HttpRequest &stHttpRequest, RequestCallbackPtr &callbackPtr, bool bUseProxy = false);
  257. /**
  258. * @brief 异步发起请求.
  259. *
  260. * @param stHttpRequest
  261. * @param httpCallbackPtr
  262. * @param addr, 请求地址, ip:port
  263. */
  264. void doAsyncRequest(TC_HttpRequest &stHttpRequest, RequestCallbackPtr &callbackPtr, const string &addr);
  265. /**
  266. * @brief 设置proxy地址
  267. *
  268. */
  269. int setProxyAddr(const char* Host, uint16_t Port);
  270. /**
  271. * @brief 设置代理的地址.
  272. *
  273. * 不通过域名解析发送,直接发送到代理服务器的ip地址)
  274. * @param sProxyAddr 格式 192.168.1.2:2345 或者 sslproxy.qq.com:2345
  275. */
  276. int setProxyAddr(const char* sProxyAddr);
  277. /**
  278. * @brief 设置绑定的地址.
  279. *
  280. * @param sProxyAddr 格式 192.168.1.2
  281. */
  282. int setBindAddr(const char* sBindAddr);
  283. /**
  284. * @brief 设置绑定的地址.
  285. *
  286. * @param addr 直接用 addr 赋值
  287. */
  288. void setProxyAddr(const struct sockaddr* addr);
  289. /**
  290. * @brief 获取代理地址, 设置代理地址后才有效
  291. * @return [description]
  292. */
  293. const struct sockaddr* getProxyAddr() const { return &_proxyAddr; }
  294. /**
  295. * @brief 启动异步处理.
  296. *
  297. * 参数已经无效(网络层有且只有一个线程)
  298. * @param num, 异步处理的线程数
  299. */
  300. void start();
  301. /**
  302. * @brief 设置超时(所有请求都只能用一种超时时间).
  303. *
  304. * @param timeout: 毫秒, 但是具体的超时精度只能在s左右
  305. */
  306. void setTimeout(int millsecond) { _data->setTimeout(millsecond); }
  307. /**
  308. * @brief 等待请求全部结束(等待毫秒精度在100ms左右).
  309. *
  310. * @param millsecond, 毫秒 -1表示永远等待
  311. */
  312. void waitForAllDone(int millsecond = -1);
  313. /**
  314. * @brief 结束线程
  315. */
  316. void terminate();
  317. protected:
  318. // typedef TC_Functor<void, TL::TLMaker<AsyncRequestPtr, int>::Result> async_process_type;
  319. typedef std::function<void(AsyncRequestPtr, int)> async_process_type;
  320. /**
  321. * @brief 超时处理.
  322. *
  323. * @param ptr
  324. */
  325. static void timeout(AsyncRequestPtr& ptr);
  326. /**
  327. * @brief 确保线程
  328. * @param _threadId [description]
  329. */
  330. void assertThreadId() { assert(_threadId == std::this_thread::get_id()); }
  331. /**
  332. * @brief 具体的网络处理逻辑
  333. */
  334. void run() ;
  335. /**
  336. * @brief 删除异步请求对象
  337. */
  338. void erase(uint32_t uniqId);
  339. /**
  340. * @brief 监控链接
  341. * @param fd [description]
  342. * @param uniqId [description]
  343. * @param events [description]
  344. */
  345. void addConnection(int fd, uint32_t uniqId, uint32_t events);
  346. /**
  347. * @brief 删除链接
  348. * @param fd [description]
  349. * @param events [description]
  350. */
  351. void delConnection(int fd);
  352. friend class AsyncRequest;
  353. protected:
  354. std::thread::id _threadId;
  355. TC_ThreadPool _tpool;
  356. http_queue_type *_data;
  357. TC_Epoller _epoller;
  358. TC_Epoller::NotifyInfo _notify;
  359. std::mutex _mutex;
  360. deque<uint64_t> _events;
  361. bool _terminate;
  362. struct sockaddr _proxyAddr;
  363. struct sockaddr _bindAddr;
  364. bool _bindAddrSet;
  365. };
  366. }
  367. #endif