加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

cocos2d-x学习篇之网络(http)篇

发布时间:2020-12-14 19:25:48 所属栏目:百科 来源:网络整理
导读:这段时间接触到cocos2d-x,拜读了csdn上很多大大的文章,尤其是小满的专栏,感觉获益不少,觉得像他们那样,边学习,边总结经验,并写出来学习过程与大家分享,我觉得是一件很值得学习的事,所以也打算把自己学习的东西和经验与大家分享,有不足之处或者错误


这段时间接触到cocos2d-x,拜读了csdn上很多大大的文章,尤其是小满的专栏,感觉获益不少,觉得像他们那样,边学习,边总结经验,并写出来学习过程与大家分享,我觉得是一件很值得学习的事,所以也打算把自己学习的东西和经验与大家分享,有不足之处或者错误的,还希望请大家能海涵并提出来,共同讨论,共同进步。好了,废话到此。

Cocos2dx 为我们封装了在cocos2dx中http的网络框架,其文件在cocos2dx引擎包的cocos2d-2.1rc0-x-2.1.2extensionsnetwork文件下的 HttpClient、HttpRequest 、HttpResponse。但是真正的底层,用的还是cURL库。。。

进行一次http交互,需要涉及的有三个类,HttpRequest用来描述一个请求。HttpResponse用来描述对应请求的响应。HttpClient是一个单例模式的类,它的职责就是负责将收到的HttpRequest对象push到发送队列中,并发送一个信号量驱动工作线程工作,工作线程再将收到的数据封装成一个HttpResponse对象push接收队列,并启用调度来派送数据。具体的后面有说道。

1.首先创建一个类,继承自cocos2d-x中的任何一个类都可以(有共同父类CCObject),并实现一个SEL_CallFuncND类型成员函数,用来做收到数据后的回调函数,函数原型为void fun(CCNode*,void*)。

2.当我们需要一次http交互的时候,我们需要new 一个CCHttpRequest对象,并设置url和请求方式(get还是post,本文只说一下get的原理,post区别不大,可以自己看),并将上面说函数设置为收到数据后的回调函数。

3.使用CCHttpClient::getInstance()单例对象,将前一步骤的CCHttpRequest对象作为参数,调用send()方法。

4.在回调函数中,将第二个参数转换成CCHttpResponse *类型,就可以通过CCHttpResponse类的方法来获取返回状态和数据等能容了。

我们先来看看具体的该怎么用,以自带的HttpClientTest.cpp为例。HttpClientTest.cpp:

[cpp] view plain copy
  1. //get请求
  2. voidHttpClientTest::onMenuGetTestClicked(cocos2d::CCObject*sender)
  3. {
  4. //test1
  5. CCHttpRequest*request=newCCHttpRequest();//创建request对象,这里new出来的对象不能使用autorelease(),原因后述
  6. request->setUrl("http://just-make-this-request-failed.com");//设置url
  7. request->setRequestType(CCHttpRequest::kHttpGet);//设置请求方式
  8. request->setResponseCallback(this,callfuncND_selector(HttpClientTest::onHttpRequestCompleted));//这是回调对象和回调函数
  9. request->setTag("GETtest1");//设置用户标识,可以通过response获取
  10. CCHttpClient::getInstance()->send(request);//使用CCHttpClient共享实例来发送request
  11. request->release();//调用release()
  12. }
  13. //waiting
  14. m_labelStatusCode->setString("waiting...");
  15. }
  16. //这里就是我们要处理接收到数据的回调函数了,sender为CCHttpClient实例指针,data为接收到的response指针
  17. voidHttpClientTest::onHttpRequestCompleted(cocos2d::CCNode*sender,void*data)
  18. CCHttpResponse*response=(CCHttpResponse*)data;
  19. if(!response)
  20. return;
  21. //获取对应request的字符串标识
  22. if(0!=strlen(response->getHttpRequest()->getTag()))
  23. CCLog("%scompleted",response->getHttpRequest()->getTag());
  24. //获取返回代码,比如200、404等
  25. intstatusCode=response->getResponseCode();
  26. charstatusString[64]={};
  27. sprintf(statusString,"HTTPStatusCode:%d,tag=%s",statusCode,response->getHttpRequest()->getTag());
  28. m_labelStatusCode->setString(statusString);
  29. CCLog("responsecode:%d",statusCode);
  30. if(!response->isSucceed())
  31. {
  32. CCLog("responsefailed");
  33. CCLog("errorbuffer:%s",response->getErrorBuffer());//可以调用getErrorBuffer()来获取错误原因
  34. return;
  35. //dumpdata
  36. std::vector<char>*buffer=response->getResponseData();//用来获取接收到的数据
  37. printf("HttpTest,dumpdata:");
  38. for(unsignedinti=0;i<buffer->size();i++)
  39. printf("%c",(*buffer)[i]);
  40. printf("n");
  41. }


基本上一个http交互就是这个样子了,下面我们深入的看一下CCHttpClient是怎么工作的,先来看一张图,画的不好或者不足之处,请勿拍砖

其实就是当我们第一次CCHttpClient::getInstance()时,CCHttpClient会将自己的成员函数dispathResponseCallbacks()挂载至CCScheduler(可以理解成一个调度者,它会定时调用所有挂载至上面的函数),并将它初始设置为停止调度。在当我们第一次调用send()发送数据时,CCHttpClient会创建一个工作线程(之后再调用send()就不会创建线程了),然后再将传递过来的CCHttpRequest对象push到发送队列s_requestQueue,并发送一个信号给工作线程,驱使其工作。工作线程首先从发送队列中取得一个CCHttpRequest对象,并new 一个CCHttpResponse对象,将参数设置给cURL,cURL会在获取到数据的填充response,工作线程将填充后的response再放到接收队列s_responseQueue中去,同时,启用调度。下一次CCScheduler就会CCHttpClient::dispatchResponseCallbacks()了,在该函数中,它会调用我们在第二步中设置给request的回调函数,并将response传递过去。基本过程就是这样。下面来详解相关的源文件。HttpRequest.h,其实这个文件没什么好说的,都有注释

copy
    classCCHttpRequest:publicCCObject
  1. public:
  2. /**请求类型枚举,可以通过setReqeustType(param)设置*/
  3. typedefenum
  4. kHttpGet,
  5. kHttpPost,
  6. kHttpUnkown,248)"> }HttpRequestType;
  7. /**Constructor
  8. BecauseHttpRequestobjectwillbeusedbetweenUItheadandnetworkthread,
  9. requestObj->autorelease()isforbiddentoavoidcrashesinCCAutoreleasePool
  10. new/retain/releasestillworks,whichmeansyouneedtoreleaseitmanually
  11. PleaserefertoHttpRequestTest.cpptofinditsusage
  12. 这里是有注释的,因为要跨线程,所以就不能用autorelease()
  13. 我们在使用HttpRequest的时候,需要自己new,然后再release下就可以了
  14. 当我们把HttpRequest传递给CCHttpClient的时候,CCHttpClient已经帮我们retain了
  15. 工作线程中,需要使用CCHttpRequest对象new一个CCHttpResponse,CCHttprequest会retain一次,所以工作线程也会release一次
  16. 具体的后文有
  17. */
  18. CCHttpRequest()
  19. _requestType=kHttpUnkown;
  20. _url.clear();
  21. _requestData.clear();
  22. _tag.clear();
  23. _pTarget=NULL;
  24. _pSelector=NULL;
  25. _pUserData=NULL;
  26. };
  27. virtual~CCHttpRequest()
  28. if(_pTarget)
  29. _pTarget->release();
  30. /**重载autorelease函数,禁止调用*/
  31. CCObject*autorelease(void)
  32. CCAssert(false,"HttpResponseisusedbetweennetworkthreadanduithread
  33. therefore,autoreleaseisforbiddenhere");
  34. returnNULL;
  35. //setter/gettersforproperties
  36. /**设置请求类型
  37. 目前支持kHttpGet和kHttpPost
  38. inlinevoidsetRequestType(HttpRequestTypetype)
  39. _requestType=type;
  40. /**返回请求类型*/
  41. inlineHttpRequestTypegetRequestType()
  42. return_requestType;
  43. };
  44. /**设置请求url
  45. voidsetUrl(constchar*url)
  46. _url=url;
  47. /**获取请求url*/
  48. char*getUrl()
  49. return_url.c_str();
  50. /**这个设置用于post方式的data数据
  51. voidsetRequestData(char*buffer,unsignedintlen)
  52. _requestData.assign(buffer,buffer+len);
  53. /**Gettherequestdatapointerback*/
  54. inlinechar*getRequestData()
  55. return&(_requestData.front());
  56. /**Getthesizeofrequestdataback*/
  57. intgetRequestDataSize()
  58. return_requestData.size();
  59. /**为每个请求设置一个字符串标示,可以通过HttpResponse->getHttpRequest->getTag()获取,因为HttpResponse会将对应的HttpRequest封装在里面
  60. */
  61. voidsetTag(char*tag)
  62. _tag=tag;
  63. /**Getthestringtagbacktoidentifytherequest.
  64. ThebestpracticeistouseitinyourMyClass::onMyHttpRequestCompleted(sender,HttpResponse*)callback
  65. char*getTag()
  66. return_tag.c_str();
  67. /**Optionfield.Youcanattachacustomeddataineachrequest,andgetitbackinresponsecallback.
  68. Butyouneedtonew/deletethedatapointermanully
  69. voidsetUserData(void*pUserData)
  70. _pUserData=pUserData;
  71. /**Getthepre-settedcustomdatapointerback.
  72. Don'tforgettodeleteit.HttpClient/HttpResponse/HttpRequestwilldonothingwiththispointer
  73. void*getUserData()
  74. return_pUserData;
  75. /**通过这个函数设置我们的数据处理回调函数
  76. voidsetResponseCallback(CCObject*pTarget,SEL_CallFuncNDpSelector)
  77. _pTarget=pTarget;
  78. _pSelector=pSelector;
  79. _pTarget->retain();
  80. /**Getthetargetofcallbackselectorfuntion,mainlyusedbyCCHttpClient*/
  81. inlineCCObject*getTarget()
  82. return_pTarget;
  83. /**Gettheselectorfunctionpointer,mainlyusedbyCCHttpClient*/
  84. inlineSEL_CallFuncNDgetSelector()
  85. return_pSelector;
  86. /**Setanycustomheaders**/
  87. voidsetHeaders(std::vector<std::string>pHeaders)
  88. _headers=pHeaders;
  89. /**Getcustomheaders**/
  90. inlinestd::vector<std::string>getHeaders()
  91. return_headers;
  92. protected:
  93. //properties
  94. HttpRequestType_requestType;///请求方式
  95. std::string_url;///请求url
  96. char>_requestData;///用于POST
  97. std::string_tag;///用户自定义标识,可以用来在response回调中区分request
  98. CCObject*_pTarget;///回调对象
  99. SEL_CallFuncND_pSelector;///回调函数例如MyLayer::onHttpResponse(CCObject*sender,void*data)
  100. void*_pUserData;///用户自定义数据,和_tag用法一样,只不过是用途不一样
  101. std::vector<std::string>_headers;///customhttpheaders
  102. };

HttpResponse.h,这个文件和HttpRequest差不多,没什么好说的
copy
    classCCHttpResponse:/**Constructor,it'susedbyCCHttpClientinternal,usersdon'tneedtocreateHttpResponsemanually
  1. @paramrequestthecorrespondingHttpRequestwhichleadstothisresponse
  2. CCHttpResponse(CCHttpRequest*request)
  3. _pHttpRequest=request;
  4. if(_pHttpRequest)
  5. _pHttpRequest->retain();
  6. _succeed=false;
  7. _responseData.clear();
  8. _errorBuffer.clear();
  9. /**Destructor,itwillbecalledinCCHttpClientinternal,
  10. usersdon'tneedtodesturctHttpResponSEObjectmanully
  11. virtual~CCHttpResponse()
  12. if(_pHttpRequest)
  13. _pHttpRequest->release();
  14. /**Overrideautoreleasemethodtopreventdevelopersfromcallingit*/
  15. CCObject*autorelease(void)
  16. CCAssert(thread
  17. therefore,autoreleaseisforbiddenhere");
  18. returnNULL;
  19. //getters,willbecalledbyusers
  20. /**GetthecorrespondingHttpRequestobjectwhichleadstothisresponse
  21. There'snopairedsetterforit,cozit'salreadysettedinclassconstructor
  22. inlineCCHttpRequest*getHttpRequest()
  23. return_pHttpRequest;
  24. /**Toseeifthehttpreqeustisreturnedsuccessfully,0); background-color:inherit">Althroughuserscanjudgeif(httpreturncode=200),wewantaneasierway
  25. Ifthisgetterreturnsfalse,youcancallgetResponseCodeandgetErrorBuffertofindmoredetails
  26. boolisSucceed()
  27. return_succeed;
  28. /**Getthehttpresponserawdata*/
  29. inlinestd::vector<char>*getResponseData()
  30. return&_responseData;
  31. /**GetthehttpresponseerrorCode
  32. *Iknowthatyouwanttoseehttp200:)
  33. intgetResponseCode()
  34. return_responseCode;
  35. /**Gettherrorbufferwhichwilltellyoumoreaboutthereasonwhyhttprequestfailed
  36. char*getErrorBuffer()
  37. return_errorBuffer.c_str();
  38. //setters,willbecalledbyCCHttpClient
  39. //usersshouldavoidinvokingthesemethods
  40. /**Setifthehttprequestisreturnedsuccessfully,0); background-color:inherit">Althroughuserscanjudgeif(httpcode==200),wewantaeasierway
  41. ThissetterismainlyusedinCCHttpClient,usersmustn'tsetitdirectly
  42. voidsetSucceed(boolvalue)
  43. _succeed=value;
  44. /**Setthehttpresponserawbuffer,isusedbyCCHttpClient
  45. voidsetResponseData(std::vector<char>*data)
  46. _responseData=*data;
  47. /**SetthehttpresponseerrorCode
  48. voidsetResponseCode(intvalue)
  49. _responseCode=value;
  50. /**Settheerrorbufferwhichwilltellyoumorethereasonwhyhttprequestfailed
  51. voidsetErrorBuffer(char*value)
  52. _errorBuffer.assign(value);
  53. boolinitWithRequest(CCHttpRequest*request);
  54. //这里要留意下,每个response中都会包含对应的request,所以能在数据处理回调函数中,获取我们在设置request的所有参数,比如像tag,userdata
  55. CCHttpRequest*_pHttpRequest;///thecorrespondingHttpRequestpointerwholeadstothisresponse
  56. bool_succeed;///toindecateifthehttpreqeustissuccessfulsimply
  57. std::vector<char>_responseData;///thereturnedrawdata.Youcanalsodumpitasastring
  58. int_responseCode;///thestatuscodereturnedfromlibcurl,e.g.200,404
  59. std::string_errorBuffer;///if_responseCode!=200,pleaseread_errorBuffertofindthereason
  60. };

说白了,CCHttpRequest和CCHttpResponse只不过是发送队列中的数据类型,和接收队列中的数据类型,是线程之间传递的参数,下面来说说CCHttpClient
HttpClient.h

copy

    //CCHttpClient是一个单例模式的类,整个程序共享一个实例对象
  1. classCCHttpClient:publicCCObject
  2. public:
  3. /**获取共享的单例对象**/
  4. staticCCHttpClient*getInstance();
  5. /**Relasethesharedinstance**/
  6. staticvoiddestroyInstance();
  7. /**
  8. *Addagetrequesttotaskqueue
  9. *@paramrequestaCCHttpRequestobject,whichincludesurl,responsecallbacketc.
  10. pleasemakesurerequest->_requestDataisclearbeforecalling"send"here.
  11. *@returnNULL
  12. voidsend(CCHttpRequest*request);
  13. /**
  14. *Changetheconnecttimeout
  15. *@paramtimeout
  16. voidsetTimeoutForConnect(intvalue){_timeoutForConnect=value;};
  17. *Getconnecttimeout
  18. *@returnint
  19. *
  20. intgetTimeoutForConnect(){return_timeoutForConnect;}
  21. *Changethedownloadtimeout
  22. *@paramvalue
  23. *@returnNULL
  24. voidsetTimeoutForRead(intvalue){_timeoutForRead=value;};
  25. *Getdownloadtimeout
  26. intgetTimeoutForRead(){return_timeoutForRead;};
  27. private:
  28. CCHttpClient();
  29. virtual~CCHttpClient();
  30. boolinit(void);
  31. *Initpthreadmutex,semaphore,andcreatenewthreadforhttprequests
  32. *@returnbool
  33. boollazyInitThreadSemphore();
  34. /**Pollfunctioncalledfrommainthreadtodispatchcallbackswhenhttprequestsfinished**/
  35. voiddispatchResponseCallbacks(floatdelta);
  36. private:
  37. int_timeoutForConnect;//连接超时时间
  38. int_timeoutForRead;//接收数据超时时间
  39. //std::stringreqId;
  40. };


HttpClient.cpp

copy
    staticpthread_ts_networkThread;//工作线程句柄
  1. staticpthread_mutex_ts_requestQueueMutex;//请求队列互斥变量
  2. staticpthread_mutex_ts_responseQueueMutex;//接收队列互斥变量
  3. staticsem_t*s_pSem=NULL;//用来驱动线程工作的信号量
  4. staticunsignedlongs_asyncRequestCount=0;//当前需要处理的request个数
  5. #ifCC_TARGET_PLATFORM==CC_PLATFORM_IOS
  6. #defineCC_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE1
  7. #else
  8. #defineCC_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE0
  9. #endif
  10. #ifCC_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE
  11. #defineCC_ASYNC_HTTPREQUEST_SEMAPHORE"ccHttpAsync"
  12. staticsem_ts_sem;
  13. #if(CC_TARGET_PLATFORM==CC_PLATFORM_WIN32)
  14. typedefintint32_t;
  15. staticboolneed_quit=false;//退出标识
  16. staticCCArray*s_requestQueue=NULL;//请求队列(下面都说request队列)
  17. staticCCArray*s_responseQueue=NULL;//接收队列(下面都说response队列)
  18. staticCCHttpClient*s_pHttpClient=NULL;//全局单例CCHttpClient对象
  19. chars_errorBuffer[CURL_ERROR_SIZE];//错误提示buffer
  20. size_t(*write_callback)(void*ptr,size_tsize,87); font-weight:bold; background-color:inherit">size_tnmemb,153); font-weight:bold; background-color:inherit">void*stream);//这个是用于cURL收到数据的回调函数
  21. //这个便是当cURL接收到数据回调的函数,也就是在这里对response进行填充,这里的声明方式和fwrite()函数一样
  22. size_twriteData(void*stream)
  23. //ptr指向接受到的数据,sizes为字节数
  24. //这里传过来的stream中保存了CCHttpResponse::_responseData
  25. char>*recvBuffer=(std::vector<char>*)stream;
  26. size_tsizes=size*nmemb;
  27. //adddatatotheendofrecvBuffer
  28. //将接受到的数据写到response中去
  29. recvBuffer->insert(recvBuffer->end(),(char*)ptr,(char*)ptr+sizes);
  30. returnsizes;
  31. //Prototypes
  32. boolconfigureCURL(CURL*handle);
  33. intprocessGetTask(CCHttpRequest*request,write_callbackcallback,153); font-weight:bold; background-color:inherit">void*stream,int32_t*errorCode);
  34. intprocessPostTask(CCHttpRequest*request,int32_t*errorCode);
  35. //intprocessDownloadTask(HttpRequest*task,void*stream,int32_t*errorCode);
  36. //工作线程
  37. void*networkThread( CCHttpRequest*request=NULL;
  38. while(true)
  39. //等待主线程发送信号,就是调用send()函数
  40. intsemWaitRet=sem_wait(s_pSem);
  41. if(semWaitRet<0){
  42. CCLog("HttpRequestasyncthreadsemaphoreerror:%sn",strerror(errno));
  43. break;
  44. //退出
  45. if(need_quit)
  46. break;
  47. //step1:sendhttprequestiftherequestQueueisn'tempty
  48. request=NULL;
  49. pthread_mutex_lock(&s_requestQueueMutex);//给request队列上锁
  50. if(0!=s_requestQueue->count())
  51. request=dynamic_cast<CCHttpRequest*>(s_requestQueue->objectAtIndex(0));//取得第一个request
  52. s_requestQueue->removeObjectAtIndex(0);//将其移除队列
  53. //这里的request的引用次数为1,因为只有在send()函数中retain了一次
  54. pthread_mutex_unlock(&s_requestQueueMutex);//request队列解锁
  55. if(NULL==request)
  56. continue;
  57. //同步调用cURL库
  58. //使用request来创建一个response
  59. CCHttpResponse*response=newCCHttpResponse(request);
  60. //在CCHttpTtpResponse构造中,会将request再retain一次
  61. request->release();
  62. //这里,只有response中有request的一次引用计数
  63. intresponseCode=-1;
  64. intretValue=0;
  65. //根据请求类型设置cURL参数
  66. switch(request->getRequestType())
  67. caseCCHttpRequest::kHttpGet://HTTPGET
  68. retValue=processGetTask(request,248)"> writeData,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> response->getResponseData(),248)"> &responseCode);
  69. caseCCHttpRequest::kHttpPost://HTTPPOST
  70. retValue=processPostTask(request,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> writeData,248)"> response->getResponseData(),108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> &responseCode);
  71. default:
  72. true,"CCHttpClient:unkownrequesttype,onlyGETandPOStaresupported");
  73. //设置返回代码
  74. response->setResponseCode(responseCode);
  75. if(retValue!=0)
  76. response->setSucceed(false);
  77. response->setErrorBuffer(s_errorBuffer);
  78. else
  79. response->setSucceed(true);
  80. //将response加入队列
  81. pthread_mutex_lock(&s_responseQueueMutex);//给response加锁
  82. s_responseQueue->addObject(response);
  83. pthread_mutex_unlock(&s_responseQueueMutex);//解锁
  84. //启动CCScheduler调度
  85. CCDirector::sharedDirector()->getScheduler()->resumeTarget(CCHttpClient::getInstance());
  86. //线程退出,清理request队列
  87. pthread_mutex_lock(&s_requestQueueMutex);
  88. s_requestQueue->removeAllObjects();
  89. pthread_mutex_unlock(&s_requestQueueMutex);
  90. s_asyncRequestCount-=s_requestQueue->count();
  91. if(s_pSem!=NULL){
  92. sem_unlink(CC_ASYNC_HTTPREQUEST_SEMAPHORE);
  93. sem_close(s_pSem);
  94. #else
  95. sem_destroy(s_pSem);
  96. #endif
  97. s_pSem=NULL;
  98. //释放互斥变量
  99. pthread_mutex_destroy(&s_requestQueueMutex);
  100. pthread_mutex_destroy(&s_responseQueueMutex);
  101. s_requestQueue->release();
  102. s_responseQueue->release();
  103. pthread_exit(NULL);
  104. return0;
  105. //设置cURL超时属性
  106. boolconfigureCURL(CURL*handle)
  107. if(!handle){
  108. returnfalse;
  109. int32_tcode;
  110. //设置错误信息缓冲
  111. code=curl_easy_setopt(handle,CURLOPT_ERRORBUFFER,s_errorBuffer);
  112. if(code!=CURLE_OK){
  113. //设置超时时间
  114. code=curl_easy_setopt(handle,CURLOPT_TIMEOUT,CCHttpClient::getInstance()->getTimeoutForRead());
  115. if(code!=CURLE_OK){
  116. true;
  117. //处理get方式请求
  118. //stream传递过来的是response->getResponseData()
  119. //关于cURL的东西这里就不多说了
  120. int*responseCode)
  121. CURLcodecode=CURL_LAST;
  122. //初始化cURL
  123. CURL*curl=curl_easy_init();
  124. do{
  125. if(!configureCURL(curl))//配置cURL
  126. /*handlecustomheaderdata*/
  127. /*createcurllinkedlist*/
  128. structcurl_slist*cHeaders=NULL;
  129. /*getcustomheaderdata(ifset)*/
  130. std::vector<std::string>headers=request->getHeaders();
  131. if(!headers.empty())
  132. for(std::vector<std::string>::iteratorit=headers.begin();it!=headers.end();it++)
  133. /*appendcustomheadersonebyone*/
  134. cHeaders=curl_slist_append(cHeaders,it->c_str());
  135. /*setcustomheadersforcurl*/
  136. code=curl_easy_setopt(curl,CURLOPT_HTTPHEADER,cHeaders);
  137. if(code!=CURLE_OK)
  138. //这里将response->_responseData设置为cURL回调函数中的stream参数
  139. code=curl_easy_perform(curl);
  140. /*freethelinkedlistforheaderdata*/
  141. curl_slist_free_all(cHeaders);
  142. code=curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,responseCode);
  143. if(code!=CURLE_OK||*responseCode!=200)
  144. code=CURLE_HTTP_RETURNED_ERROR;
  145. }while(0);
  146. if(curl){
  147. curl_easy_cleanup(curl);
  148. return(code==CURLE_OK?0:1);
  149. //这个就不说了,其实都一样的,cURL承担了所有工作
  150. CURLcodecode=CURL_LAST;
  151. if(!configureCURL(curl)){
  152. /*handlecustomheaderdata*/
  153. /*createcurllinkedlist*/
  154. structcurl_slist*cHeaders=NULL;
  155. /*getcustomheaderdata(ifset)*/
  156. std::vector<std::string>headers=request->getHeaders();
  157. if(!headers.empty())
  158. for(std::vector<std::string>::iteratorit=headers.begin();it!=headers.end();it++)
  159. /*appendcustomheadersonebyone*/
  160. cHeaders=curl_slist_append(cHeaders,it->c_str());
  161. /*setcustomheadersforcurl*/
  162. code=curl_easy_setopt(curl,cHeaders);
  163. code=curl_easy_perform(curl);
  164. if(code!=CURLE_OK||*responseCode!=200){
  165. code=CURLE_HTTP_RETURNED_ERROR;
  166. }while(0);
  167. //返回共享实例
  168. CCHttpClient*CCHttpClient::getInstance()
  169. if(s_pHttpClient==NULL){
  170. s_pHttpClient=newCCHttpClient();
  171. returns_pHttpClient;
  172. voidCCHttpClient::destroyInstance()
  173. CCAssert(s_pHttpClient,"");
  174. //将CCHttpClient::dispatchResponseCallbacks()函数从CCShecduler中取消挂载
  175. CCDirector::sharedDirector()->getScheduler()->unscheduleSelector(schedule_selector(CCHttpClient::dispatchResponseCallbacks),s_pHttpClient);
  176. s_pHttpClient->release();
  177. CCHttpClient::CCHttpClient()
  178. :_timeoutForConnect(30)
  179. ,_timeoutForRead(60)
  180. //将成员函数dispatchTesponseCallbacks()挂载至CCSheduler
  181. CCDirector::sharedDirector()->getScheduler()->scheduleSelector(
  182. schedule_selector(CCHttpClient::dispatchResponseCallbacks),false);
  183. //初始化为停止调度,由工作线程接收到了数据之后启用调度
  184. CCDirector::sharedDirector()->getScheduler()->pauseTarget(this);
  185. CCHttpClient::~CCHttpClient()
  186. need_quit=true;
  187. sem_post(s_pSem);
  188. s_pHttpClient=NULL;
  189. //只有在第一次调用send()时调用,去初始化队列、创建线程、初始化互斥变量等
  190. boolCCHttpClient::lazyInitThreadSemphore()
  191. else{
  192. s_pSem=sem_open(CC_ASYNC_HTTPREQUEST_SEMAPHORE,O_CREAT,0644,0);
  193. if(s_pSem==SEM_FAILED){
  194. CCLog("OpenHttpRequestSemaphorefailed");
  195. s_pSem=NULL;
  196. intsemRet=sem_init(&s_sem,0);
  197. if(semRet<0){
  198. CCLog("InitHttpRequestSemaphorefailed");
  199. s_pSem=&s_sem;
  200. s_requestQueue=newCCArray();
  201. s_requestQueue->init();
  202. s_responseQueue=newCCArray();
  203. s_responseQueue->init();
  204. pthread_mutex_init(&s_requestQueueMutex,NULL);
  205. pthread_mutex_init(&s_responseQueueMutex,NULL);
  206. pthread_create(&s_networkThread,NULL,networkThread,248)"> pthread_detach(s_networkThread);
  207. //Addagettasktoqueue
  208. voidCCHttpClient::send(CCHttpRequest*request)
  209. //第一次调用的时候初始化
  210. if(false==lazyInitThreadSemphore())
  211. if(!request)
  212. //将当前需要处理的request个数++
  213. ++s_asyncRequestCount;
  214. //在这里对request进行第一次retain,
  215. request->retain();
  216. //这里request的引用次数为1
  217. pthread_mutex_lock(&s_requestQueueMutex);//request队列加锁
  218. s_requestQueue->addObject(request);//push到request队列
  219. //发送信号唤醒工作线程
  220. //将response队列数据分发
  221. voidCCHttpClient::dispatchResponseCallbacks(floatdelta)
  222. //CCLog("CCHttpClient::dispatchResponseCallbacksisrunning");
  223. CCHttpResponse*response=NULL;
  224. pthread_mutex_lock(&s_responseQueueMutex);//给response队列上锁
  225. if(s_responseQueue->count())
  226. response=dynamic_cast<CCHttpResponse*>(s_responseQueue->objectAtIndex(0));//取出response
  227. s_responseQueue->removeObjectAtIndex(0);//将其从response队列移除
  228. pthread_mutex_unlock(&s_responseQueueMutex);//解锁
  229. if(response)
  230. --s_asyncRequestCount;
  231. CCHttpRequest*request=response->getHttpRequest();
  232. CCObject*pTarget=request->getTarget();//获取request回调函数的对象
  233. SEL_CallFuncNDpSelector=request->getSelector();//获取回调函数
  234. if(pTarget&&pSelector)
  235. (pTarget->*pSelector)((CCNode*)//调用回调函数,并把本单例对象和response传递给我们设置在request中的回调函数
  236. response->release();
  237. if(0==s_asyncRequestCount)//如果没有没有请求,停止调度
  238. }

花了大半天时间,终于写的差不多了,其实我当初是想看看cocos2d-x是怎样封装socket这一块的,结果是这样,用的cURL库。。。
这篇文章是我的处女做,哪里有不好的地方大家提出来共同进步,欢迎交流

本人今年刚毕业,接触cocos2d-x也才两个月(写的不好不要扔砖就好),前一个多月一直在搞粒子系统这块,这几天把改造后的粒子系统工具开发完了,时间稍微多点,就看看其他的模块了,看完了收获也不少,由于经常逛csdn,拜读大神的文章,所以就想着咱也来发表一遍学习心得吧,这样既可以提高自己,也可以和大家交流交流心得,更重要的是我发现写博客可以提升学习的兴趣

好了,就到这里了,以后有时间再继续

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读