cocos2d-x 10.1版本 http 链接
这是根据 cocos2d-x-2.0 修改的。
1 /******************************************************************** 2 * Copyright(C) 2012 Ambition( All rights reserved. ) 3 * Created: 2012/09/18 11:21 4 * File base: HSBaseHttp.h 5 * Author: Ambition 6 * 7 * Purpose: 8 *********************************************************************/ 9 #ifndef __HSBaseHttp_H__ 10 #define __HSBaseHttp_H__ 11 #pragma once 12 #include "cocos2d.h" 13 #include "curl.h" 14 #include <queue> 15 #include <pthread.h> 16 #include <semaphore.h> 17 #include <errno.h> 18 #include "HSHttpRequest.h" 19 #include "HSHttpResponse.h" 20 using namespace cocos2d; 21 22 #if WIN32 23 #pragma comment(lib,"libcurl_imp.lib") 24 #pragma comment(lib,"pthreadVCE2.lib") 25 #endif 26 27 28 class HSBaseHttp : public SelectorProtocol,public CCObject 29 { 30 31 public: 32 HSBaseHttp(); 33 virtual ~HSBaseHttp(); 34 35 private: 36 int iTimeoutForConnect; //链接超时时间 37 int iTimeoutForRead; //读取超时时间 38 public: 39 //得到一个实例 40 static HSBaseHttp* GetInstance(); 41 //销毁实例 42 static void DestroyInstance(); 43 //发送请求 44 void Send(HSHttpRequest* request); 45 void SetTimeoutForConnect(int value); 46 47 int GetTimeoutForConnect(); 48 49 void SetTimeoutForRead(int value); 50 51 int GetTimeoutForRead(); 52 53 54 55 private: 56 //销毁回调 57 void DispatchResponseCallbacks(float delta); 58 //线程信号初始化 59 bool LazyInitThreadSemphore(); 60 }; 61 62 63 #endif // __HSBaseHttp_H__
1 #include "HSBaseHttp.h" 2 3 4 //static member 5 static HSBaseHttp* s_pBaseHttp = NULL; // pointer to singleton 6 7 //线程锁 8 static pthread_t s_networkThread; 9 static pthread_mutex_t s_requestQueueMutex; 10 static pthread_mutex_t s_responseQueueMutex; 11 static sem_t * s_pSem = NULL; 12 static unsigned long s_asyncRequestCount = 0; 13 14 static bool need_quit = false; 15 static CCArray* s_requestQueue = NULL; //请求队列 16 static CCArray* s_responseQueue = NULL; //响应队列 17 18 #if CC_TARGET_PLATFORM == CC_PLATFORM_IOS 19 #define CC_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE 1 20 #else 21 #define CC_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE 0 22 #endif 23 24 #if CC_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE 25 #define CC_ASYNC_HTTPREQUEST_SEMAPHORE "ccHttpAsync" 26 #else 27 static sem_t s_sem; 28 #endif 29 30 #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) 31 typedef int int32_t; 32 #endif 33 34 static char s_errorBuffer[CURL_ERROR_SIZE]; 35 36 typedef size_t (*write_callback)(void *ptr, size_t size, size_t nmemb, void *stream); 37 38 ////////////////////////////////////////////////////////////////////////// 39 // C 函数实现 40 ////////////////////////////////////////////////////////////////////////// 41 42 size_t writeData(void *ptr, size_t size, size_t nmemb, void *stream) 43 { 44 std::vector<char> *recvBuffer = (std::vector<char>*)stream; 45 size_t sizes = size * nmemb; 46 47 recvBuffer->clear(); 48 recvBuffer->assign((char*)ptr, (char*)ptr + sizes); 49 CCLog("...%s ... ",(char*)ptr); 50 51 return sizes; 52 } 53 54 bool ConfigureCURL(CURL *handle) 55 { 56 if (!handle) { 57 return false; 58 } 59 60 int32_t code; 61 code = curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, s_errorBuffer); 62 if (code != CURLE_OK) { 63 return false; 64 } 65 //设置超时时间 防止一直等待 66 code = curl_easy_setopt(handle, CURLOPT_TIMEOUT, HSBaseHttp::GetInstance()->GetTimeoutForRead()); 67 if (code != CURLE_OK) { 68 return false; 69 } 70 code = curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT, HSBaseHttp::GetInstance()->GetTimeoutForConnect()); 71 if (code != CURLE_OK) { 72 return false; 73 } 74 75 return true; 76 } 77 78 //Post 模式设置 79 int ProcessPostTask(HSHttpRequest *request, write_callback callback, void *stream, int32_t *responseCode) 80 { 81 CURLcode code = CURL_LAST; 82 CURL *curl = curl_easy_init(); 83 84 do { 85 if (!ConfigureCURL(curl)) { 86 break; 87 } 88 89 code = curl_easy_setopt(curl, CURLOPT_URL, request->GetUrl()); 90 if (code != CURLE_OK) { 91 break; 92 } 93 code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback); 94 if (code != CURLE_OK) { 95 break; 96 } 97 code = curl_easy_setopt(curl, CURLOPT_WRITEDATA, stream); 98 if (code != CURLE_OK) { 99 break; 100 } 101 code = curl_easy_setopt(curl, CURLOPT_POST, 1); 102 if (code != CURLE_OK) { 103 break; 104 } 105 code = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request->GetRequestData()); 106 if (code != CURLE_OK) { 107 break; 108 } 109 code = curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, request->GetRequestDataSize()); 110 if (code != CURLE_OK) { 111 break; 112 } 113 code = curl_easy_perform(curl); 114 if (code != CURLE_OK) { 115 break; 116 } 117 118 code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, responseCode); 119 if (code != CURLE_OK || *responseCode != 200) { 120 code = CURLE_HTTP_RETURNED_ERROR; 121 } 122 } while (0); 123 if (curl) { 124 curl_easy_cleanup(curl); 125 } 126 127 return (code == CURLE_OK ? 0 : 1); 128 } 129 130 //Get模式设置 131 int ProcessGetTask(HSHttpRequest *request, write_callback callback, void *stream, int *responseCode) 132 { 133 CURLcode code = CURL_LAST; 134 CURL *curl = curl_easy_init(); 135 136 do { 137 if (!ConfigureCURL(curl)) 138 { 139 break; 140 } 141 142 code = curl_easy_setopt(curl, CURLOPT_URL, request->GetUrl()); 143 if (code != CURLE_OK) 144 { 145 break; 146 } 147 148 code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback); 149 if (code != CURLE_OK) 150 { 151 break; 152 } 153 154 code = curl_easy_setopt(curl, CURLOPT_WRITEDATA, stream); 155 if (code != CURLE_OK) 156 { 157 break; 158 } 159 160 code = curl_easy_perform(curl); 161 if (code != CURLE_OK) 162 { 163 break; 164 } 165 166 code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, responseCode); 167 if (code != CURLE_OK || *responseCode != 200) 168 { 169 code = CURLE_HTTP_RETURNED_ERROR; 170 } 171 } while (0); 172 173 if (curl) { 174 curl_easy_cleanup(curl); 175 } 176 177 return (code == CURLE_OK ? 0 : 1); 178 } 179 180 181 static void* NetworkThread(void *data) 182 { 183 HSHttpRequest *request = NULL; 184 185 while (true) 186 { 187 // Wait for http request tasks from main thread 188 int semWaitRet = sem_wait(s_pSem); 189 if (semWaitRet < 0) { 190 CCLog("HSBaseHttp: HttpRequest async thread semaphore error: %s\n", strerror(errno)); 191 break; 192 } 193 194 if (need_quit) 195 { 196 break; 197 } 198 199 // step 1: send http request if the requestQueue isn't empty 200 request = NULL; 201 202 pthread_mutex_lock(&s_requestQueueMutex); //Get request task from queue 203 if (0 != s_requestQueue->count()) 204 { 205 request = dynamic_cast<HSHttpRequest*>(s_requestQueue->objectAtIndex(0)); 206 s_requestQueue->removeObjectAtIndex(0); 207 // request's refcount = 1 here 208 } 209 pthread_mutex_unlock(&s_requestQueueMutex); 210 211 if (NULL == request) 212 { 213 continue; 214 } 215 216 // step 2: libcurl sync access 217 218 // Create a HttpResponse object, the default setting is http access failed 219 HSHttpResponse *response = new HSHttpResponse(request); 220 221 // request's refcount = 2 here, it's retained by HttpRespose constructor 222 request->release(); 223 // ok, refcount = 1 now, only HttpResponse hold it. 224 225 int responseCode = -1; 226 int retValue = 0; 227 228 // Process the request -> get response packet 229 switch (request->GetRequestType()) 230 { 231 case HSHttpRequest::HTTP_MODE_GET: // HTTP GET 232 retValue = ProcessGetTask(request, writeData, response->GetResponseData(), &responseCode); 233 break; 234 235 case HSHttpRequest::HTTP_MODE_POST: // HTTP POST 236 retValue = ProcessPostTask(request, writeData, response->GetResponseData(), &responseCode); 237 break; 238 239 default: 240 CCAssert(true, "CCHttpClient: unkown request type, only GET and POSt are supported"); 241 break; 242 } 243 244 // write data to HttpResponse 245 response->SetResponseCode(responseCode); 246 247 if (retValue != 0) 248 { 249 response->SetSucceed(false); 250 response->SetErrorBuffer(s_errorBuffer); 251 } 252 else 253 { 254 response->SetSucceed(true); 255 } 256 257 258 // add response packet into queue 259 pthread_mutex_lock(&s_responseQueueMutex); 260 s_responseQueue->addObject(response); 261 pthread_mutex_unlock(&s_responseQueueMutex); 262 263 // resume dispatcher selector 264 CCScheduler::sharedScheduler()->resumeTarget(HSBaseHttp::GetInstance()); 265 } 266 267 // cleanup: if worker thread received quit signal, clean up un-completed request queue 268 pthread_mutex_lock(&s_requestQueueMutex); 269 s_requestQueue->removeAllObjects(); 270 pthread_mutex_unlock(&s_requestQueueMutex); 271 s_asyncRequestCount -= s_requestQueue->count(); 272 273 if (s_pSem != NULL) { 274 #if CC_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE 275 sem_unlink(CC_ASYNC_HTTPREQUEST_SEMAPHORE); 276 sem_close(s_pSem); 277 #else 278 sem_destroy(s_pSem); 279 #endif 280 281 s_pSem = NULL; 282 283 pthread_mutex_destroy(&s_requestQueueMutex); 284 pthread_mutex_destroy(&s_responseQueueMutex); 285 286 s_requestQueue->release(); 287 s_responseQueue->release(); 288 } 289 290 pthread_exit(NULL); 291 292 return 0; 293 } 294 295 HSBaseHttp::HSBaseHttp() 296 { 297 this->iTimeoutForConnect = 30; 298 this->iTimeoutForRead = 60; 299 CCScheduler::sharedScheduler()->scheduleSelector(schedule_selector(HSBaseHttp::DispatchResponseCallbacks), this, 0, false); 300 CCScheduler::sharedScheduler()->pauseTarget(this); 301 } 302 303 HSBaseHttp::~HSBaseHttp() 304 { 305 need_quit = true; 306 307 if (s_pSem != NULL) 308 { 309 sem_post(s_pSem); 310 } 311 CCScheduler::sharedScheduler()->unscheduleSelector(schedule_selector(HSBaseHttp::DispatchResponseCallbacks), this); 312 } 313 314 HSBaseHttp* HSBaseHttp::GetInstance() 315 { 316 if (s_pBaseHttp == NULL) 317 { 318 s_pBaseHttp = new HSBaseHttp(); 319 } 320 321 return s_pBaseHttp; 322 } 323 324 void HSBaseHttp::DestroyInstance() 325 { 326 CCScheduler::sharedScheduler()->unscheduleSelector(schedule_selector(HSBaseHttp::DispatchResponseCallbacks),HSBaseHttp::GetInstance()); 327 CC_SAFE_RELEASE_NULL(s_pBaseHttp); 328 } 329 330 void HSBaseHttp::DispatchResponseCallbacks(float delta) 331 { 332 HSHttpResponse* response = NULL; 333 334 pthread_mutex_lock(&s_responseQueueMutex); 335 if (s_responseQueue->count()) 336 { 337 response = dynamic_cast<HSHttpResponse*>(s_responseQueue->objectAtIndex(0)); 338 s_responseQueue->removeObjectAtIndex(0); 339 } 340 pthread_mutex_unlock(&s_responseQueueMutex); 341 342 if (response) 343 { 344 --s_asyncRequestCount; 345 346 HSHttpRequest* request = response->GetHttpRequest(); 347 SelectorProtocol* pTarget = request->GetTarget(); 348 SEL_CallFuncND pSelector = request->GetSelector(); 349 350 if (pTarget && pSelector) 351 { 352 (pTarget->*pSelector)((CCNode *)this, response); 353 } 354 355 response->release(); 356 } 357 358 if (0 == s_asyncRequestCount) 359 { 360 CCScheduler::sharedScheduler()->pauseTarget(this); 361 } 362 } 363 364 bool HSBaseHttp::LazyInitThreadSemphore() 365 { 366 if(s_pSem != NULL) 367 return false; 368 369 #if CC_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE 370 s_pSem = sem_open(CC_ASYNC_HTTPREQUEST_SEMAPHORE, O_CREAT, 0644, 0); 371 if (s_pSem == SEM_FAILED) { 372 CCLog("Open HttpRequest Semaphore failed"); 373 s_pSem = NULL; 374 return false; 375 } 376 #else 377 int semRet = sem_init(&s_sem, 0, 0); 378 if (semRet < 0) { 379 CCLog("Init HttpRequest Semaphore failed"); 380 return false; 381 } 382 383 s_pSem = &s_sem; 384 #endif 385 386 s_requestQueue = CCArray::array(); 387 s_requestQueue->init(); 388 s_requestQueue->retain(); 389 390 s_responseQueue = CCArray::array(); 391 s_responseQueue->init(); 392 s_responseQueue->retain(); 393 394 pthread_mutex_init(&s_requestQueueMutex, NULL); 395 pthread_mutex_init(&s_responseQueueMutex, NULL); 396 397 pthread_create(&s_networkThread, NULL, NetworkThread, NULL); 398 pthread_detach(s_networkThread); 399 400 need_quit = false; 401 402 return true; 403 404 } 405 406 void HSBaseHttp::Send(HSHttpRequest* request) 407 { 408 if (!LazyInitThreadSemphore() || !request) 409 { 410 return; 411 } 412 413 ++s_asyncRequestCount; 414 415 request->retain(); 416 417 pthread_mutex_lock(&s_requestQueueMutex); 418 s_requestQueue->addObject(request); 419 pthread_mutex_unlock(&s_requestQueueMutex); 420 421 // Notify thread start to work 422 sem_post(s_pSem); 423 } 424 425 void HSBaseHttp::SetTimeoutForConnect( int value ) 426 { 427 this->iTimeoutForConnect = value; 428 } 429 430 int HSBaseHttp::GetTimeoutForConnect() 431 { 432 return this->iTimeoutForConnect; 433 } 434 435 void HSBaseHttp::SetTimeoutForRead( int value ) 436 { 437 this->iTimeoutForRead = value; 438 } 439 440 int HSBaseHttp::GetTimeoutForRead() 441 { 442 return this->iTimeoutForRead; 443 }
1 /******************************************************************** 2 * Copyright(C) 2012 Ambition( All rights reserved. ) 3 * Created: 2012/09/20 9:41 4 * File base: HSHttpRequest.h 5 * Author: Ambition 6 * 7 * Purpose: 请求消息发送和设置(不是发送的具体数据) 8 *********************************************************************/ 9 #ifndef __HSHttpRequest_H__ 10 #define __HSHttpRequest_H__ 11 #pragma once 12 #include "cocos2d.h" 13 using namespace cocos2d; 14 15 class HSHttpRequest : public CCObject 16 { 17 public: 18 HSHttpRequest(void); 19 ~HSHttpRequest(void); 20 21 public: 22 typedef enum 23 { 24 HTTP_MODE_GET, 25 HTTP_MODE_POST, 26 HTTP_MODE_UNKOWN, 27 }HttpRequestType; 28 29 protected: 30 SelectorProtocol* pTarget; 31 SEL_CallFuncND pSelector; //回调选择器 32 HttpRequestType requestType; //请求类型 33 string strUrl; 34 vector<char> vRequestData; 35 string tag; 36 void* pUserData; //用语在请求前添加的标志 例(Ambition:xxxxxx) 37 38 public: 39 SelectorProtocol* GetTarget(); 40 SEL_CallFuncND GetSelector(); 41 void SetRequestType(HttpRequestType type); 42 HttpRequestType GetRequestType(); 43 44 void SetUrl(const char* url); 45 const char* GetUrl(); 46 47 void SetRequestData(const char* buffer, unsigned int len); 48 char* GetRequestData(); 49 50 int GetRequestDataSize(); 51 52 void SetResponseCallback(SelectorProtocol* pTarget, cocos2d::SEL_CallFuncND pSelector); 53 54 void SetTag(const char* tag); 55 const char* GetTag(); 56 57 void SetUserData(void* pUserData); 58 void* GetUserData(); 59 }; 60 61 62 #endif // __HSHttpRequest_H__
1 #include "HSHttpRequest.h" 2 3 HSHttpRequest::HSHttpRequest(void) 4 { 5 this->requestType = HTTP_MODE_UNKOWN; 6 this->vRequestData.clear(); 7 this->tag.clear(); 8 this->pTarget = NULL; 9 this->pSelector = NULL; 10 this->pUserData = NULL; 11 } 12 13 HSHttpRequest::~HSHttpRequest(void) 14 { 15 } 16 17 SelectorProtocol* HSHttpRequest::GetTarget() 18 { 19 return this->pTarget; 20 } 21 22 cocos2d::SEL_CallFuncND HSHttpRequest::GetSelector() 23 { 24 return pSelector; 25 } 26 27 HSHttpRequest::HttpRequestType HSHttpRequest::GetRequestType() 28 { 29 return this->requestType; 30 } 31 32 void HSHttpRequest::SetUrl( const char* url ) 33 { 34 strUrl = url; 35 } 36 37 const char* HSHttpRequest::GetUrl() 38 { 39 return strUrl.c_str(); 40 } 41 42 void HSHttpRequest::SetRequestData( const char* buffer, unsigned int len ) 43 { 44 vRequestData.assign(buffer, buffer + len); 45 } 46 47 char* HSHttpRequest::GetRequestData() 48 { 49 return &(vRequestData.front()); 50 } 51 52 int HSHttpRequest::GetRequestDataSize() 53 { 54 return vRequestData.size(); 55 } 56 57 void HSHttpRequest::SetRequestType( HttpRequestType type ) 58 { 59 requestType = type; 60 } 61 62 void HSHttpRequest::SetResponseCallback( SelectorProtocol* pTarget, cocos2d::SEL_CallFuncND pSelector ) 63 { 64 this->pTarget = pTarget; 65 this->pSelector = pSelector; 66 67 if (this->pTarget) 68 { 69 //this->pTarget->retain(); 70 //如果有问题以后修改 71 } 72 } 73 74 void HSHttpRequest::SetTag( const char* tag ) 75 { 76 this->tag = tag; 77 } 78 79 const char* HSHttpRequest::GetTag() 80 { 81 return this->tag.c_str(); 82 } 83 84 void HSHttpRequest::SetUserData( void* pUserData ) 85 { 86 this->pUserData = pUserData; 87 } 88 89 void* HSHttpRequest::GetUserData() 90 { 91 return this->pUserData; 92 }
1 /******************************************************************** 2 * Copyright(C) 2012 Ambition( All rights reserved. ) 3 * Created: 2012/09/20 9:42 4 * File base: HSHttpResponse.h 5 * Author: Ambition 6 * 7 * Purpose: 响应包含返回的具体数据,但是没有解析 8 *********************************************************************/ 9 #ifndef __HSHttpResponse_H__ 10 #define __HSHttpResponse_H__ 11 #pragma once 12 #include "HSHttpRequest.h" 13 14 15 class HSHttpResponse : public CCObject 16 { 17 public: 18 HSHttpResponse(HSHttpRequest* request); 19 virtual ~HSHttpResponse(void); 20 21 protected: 22 HSHttpRequest* pHttpRequest; //对应的请求指针 23 bool isSucceed; //是否成功 24 vector<char> vResponseData; 25 int iResponseCode; //响应代码 26 string strErrorBuffer; //错误信息缓存 27 28 public: 29 HSHttpRequest* GetHttpRequest(); 30 31 void SetResponseData(std::vector<char>* data); 32 vector<char>* GetResponseData(); 33 34 void SetResponseCode(int value); 35 int GetResponseCode(); 36 37 void SetSucceed(bool value); 38 bool GetSucceed(); 39 40 void SetErrorBuffer(const char* value); 41 const char* GetErrorBuffer(); 42 43 }; 44 45 #endif // __HSHttpResponse_H__
1 #include "HSHttpResponse.h" 2 3 HSHttpResponse::HSHttpResponse(HSHttpRequest* request) 4 { 5 this->pHttpRequest = request; 6 if (this->pHttpRequest) 7 { 8 this->pHttpRequest->retain(); 9 } 10 this->isSucceed = false; 11 this->vResponseData.clear(); 12 this->strErrorBuffer.clear(); 13 } 14 15 HSHttpResponse::~HSHttpResponse(void) 16 { 17 if (this->pHttpRequest) 18 { 19 this->pHttpRequest->release(); 20 } 21 } 22 23 HSHttpRequest* HSHttpResponse::GetHttpRequest() 24 { 25 return this->pHttpRequest; 26 } 27 28 void HSHttpResponse::SetResponseData( std::vector<char>* data ) 29 { 30 vResponseData = *data; 31 } 32 33 vector<char>* HSHttpResponse::GetResponseData() 34 { 35 return &vResponseData; 36 } 37 38 void HSHttpResponse::SetResponseCode( int value ) 39 { 40 iResponseCode = value; 41 } 42 43 int HSHttpResponse::GetResponseCode() 44 { 45 return this->iResponseCode; 46 } 47 48 void HSHttpResponse::SetSucceed( bool value ) 49 { 50 isSucceed = value; 51 } 52 53 bool HSHttpResponse::GetSucceed() 54 { 55 return this->isSucceed; 56 } 57 58 void HSHttpResponse::SetErrorBuffer( const char* value ) 59 { 60 strErrorBuffer.clear(); 61 strErrorBuffer.assign(value); 62 } 63 64 const char* HSHttpResponse::GetErrorBuffer() 65 { 66 return strErrorBuffer.c_str(); 67 }
测试代码:
1 HSHttpRequest* request = new HSHttpRequest(); 2 request->SetUrl("http://220.194.62.22/wapgame/a.jsp"); 3 request->SetRequestType(HSHttpRequest::HTTP_MODE_POST); 4 request->SetResponseCallback(this, callfuncND_selector(HelloWorld::onHttpRequestCompleted)); 5 6 // write the post data 7 const char* postData = "visitor=cocos2d&TestSuite=Extensions Test/NetowrkTest"; 8 request->SetRequestData(postData, strlen(postData)); 9 request->SetTag("POST test"); 10 HSBaseHttp::GetInstance()->Send(request); 11 request->release();