Lite2D的HttpClient

梦想游戏人
目录:
C/C++

封装了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();
}
Scroll Up