Lite2D的HttpClient
封装了curl 由于网络是独立的一个线程 所以需要线程同步
下面是Director的同步代码
void Director::addFuncToMainThread(const std::function<void()>& func) { _mutex_mainThread.lock(); _queue_other_thread_func.push_back(func); _mutex_mainThread.unlock(); } void Director::processOtherThreadFunc() { // for (int i = 0;i<_queue_other_thread_func.size(); ++i) // { // _queue_other_thread_func[i](); // } _mutex_mainThread.lock(); for (int i = 0; i < _queue_other_thread_func.size(); ++i) { _queue_other_thread_func[i](); } _queue_other_thread_func.clear(); _mutex_mainThread.unlock(); }
下面是Lite2D 的HttpClient的实现
#include"HttpClient.h" #include "HttpRequest.h" #include "HttpRespone.h" #include "../base/Director.h" #include "../3party/curl/curl.h" static int write_data(void *buffer, size_t size, size_t buffer_size, void *_respone) { HttpRespone *respone = (HttpRespone*)_respone; HttpRequest*request = respone->getHttpRequest(); respone->writeData(buffer, buffer_size); request->release(); Director::getInstance()->addFuncToMainThread([=]() { const HttpCallBack & x = request->getHttpCallback(); x(request, respone); request->release(); respone->release(); }); return 0; } HttpClient* HttpClient::getInstance() { static HttpClient*ins = nullptr; if (ins == nullptr) { ins = new HttpClient; } return ins; } void HttpClient::doRequest_curl(HttpRequest*request) { HttpRespone *respone = HttpRespone::create(); CURL*easy_handle = curl_easy_init(); curl_easy_setopt(easy_handle, CURLOPT_URL, request->getUrl().c_str()); curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, respone); curl_easy_setopt(easy_handle, CURLOPT_TIMEOUT, this->_time_read); curl_easy_setopt(easy_handle, CURLOPT_CONNECTTIMEOUT, this->_time_connect); // do post or get if (request->getHttpType() == HttpType::POST) {//post curl_easy_setopt(easy_handle, CURLOPT_HTTPPOST, 1); curl_easy_setopt(easy_handle, CURLOPT_POSTFIELDS, request->getPostData().c_str()); } else if (request->getHttpType() == HttpType::GET) {//get curl_easy_setopt(easy_handle, CURLOPT_HTTPGET, 1); } respone->setHttpRequest(request); request->setCURLhandle(easy_handle); // perform auto succ = curl_easy_perform(easy_handle); // do http status code 404 200 etc. int code; curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE, &code); std::cout << " code:" << code << std::endl; switch (code) { case 200: { respone->setHttpStatus(HttpStatus::OK); }break; case 0: {//timeout such read and connect respone->setHttpStatus(HttpStatus::TIMEOUT); write_data(0, 0, 0, respone); }break; default: {//404 etc. respone->setHttpStatus(HttpStatus::NETERROR); } break; } respone->setOriginHttpCode(code); } void HttpClient::workFunc() { while (true) { HttpRequest* request; _mutex.lock(); if (_queue_request.size() <= 0) { _condition.wait(_mutex); } request = _queue_request.front(); _queue_request.pop(); _mutex.unlock(); // log("net thread %d", _queue_request.size()); this->doRequest_curl(request); } } HttpClient::HttpClient() { this->_time_connect = 5; this->_time_read = 10; curl_global_init(CURL_GLOBAL_WIN32); auto t = std::thread([=] { this->workFunc(); }); t.detach(); } void HttpClient::send(HttpRequest*request) { request->retain(); _mutex.lock(); _queue_request.push(request); _mutex.unlock(); _condition.notify_one(); } HttpClient::~HttpClient() { _condition.notify_all(); }