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

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

发布时间:2020-12-14 21:44:27 所属栏目:百科 来源:网络整理
导读:转自:http://blog.csdn.net/duotianshi86/article/details/10216383 这段时间接触到cocos2d-x,拜读了csdn上很多大大的文章,尤其是小满的专栏,感觉获益不少,觉得像他们那样,边学习,边总结经验,并写出来学习过程与大家分享,我觉得是一件很值得学习的

转自:http://blog.csdn.net/duotianshi86/article/details/10216383

这段时间接触到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); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> }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. inlinevoidsetUrl(constchar*url)
  46. _url=url;
  47. /**获取请求url*/
  48. inlineconstchar*getUrl()
  49. return_url.c_str();
  50. /**这个设置用于post方式的data数据
  51. inlinevoidsetRequestData(constchar*buffer,unsignedintlen)
  52. _requestData.assign(buffer,buffer+len);
  53. /**Gettherequestdatapointerback*/
  54. inlinechar*getRequestData()
  55. return&(_requestData.front());
  56. /**Getthesizeofrequestdataback*/
  57. inlineintgetRequestDataSize()
  58. return_requestData.size();
  59. /**为每个请求设置一个字符串标示,可以通过HttpResponse->getHttpRequest->getTag()获取,因为HttpResponse会将对应的HttpRequest封装在里面
  60. */
  61. inlinevoidsetTag(constchar*tag)
  62. _tag=tag;
  63. /**Getthestringtagbacktoidentifytherequest.
  64. ThebestpracticeistouseitinyourMyClass::onMyHttpRequestCompleted(sender,HttpResponse*)callback
  65. inlineconstchar*getTag()
  66. return_tag.c_str();
  67. /**Optionfield.Youcanattachacustomeddataineachrequest,andgetitbackinresponsecallback.
  68. Butyouneedtonew/deletethedatapointermanully
  69. inlinevoidsetUserData(void*pUserData)
  70. _pUserData=pUserData;
  71. /**Getthepre-settedcustomdatapointerback.
  72. Don'tforgettodeleteit.HttpClient/HttpResponse/HttpRequestwilldonothingwiththispointer
  73. inlinevoid*getUserData()
  74. return_pUserData;
  75. /**通过这个函数设置我们的数据处理回调函数
  76. inlinevoidsetResponseCallback(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. inlinevoidsetHeaders(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. std::vector<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:publicCCObject
  1. /**Constructor,it'susedbyCCHttpClientinternal,usersdon'tneedtocreateHttpResponsemanually
  2. @paramrequestthecorrespondingHttpRequestwhichleadstothisresponse
  3. CCHttpResponse(CCHttpRequest*request)
  4. _pHttpRequest=request;
  5. if(_pHttpRequest)
  6. _pHttpRequest->retain();
  7. _succeed=false;
  8. _responseData.clear();
  9. _errorBuffer.clear();
  10. /**Destructor,itwillbecalledinCCHttpClientinternal,
  11. usersdon'tneedtodesturctHttpResponSEObjectmanully
  12. virtual~CCHttpResponse()
  13. if(_pHttpRequest)
  14. _pHttpRequest->release();
  15. /**Overrideautoreleasemethodtopreventdevelopersfromcallingit*/
  16. CCObject*autorelease(void)
  17. CCAssert(false,"HttpResponseisusedbetweennetworkthreadanduithread
  18. therefore,autoreleaseisforbiddenhere");
  19. returnNULL;
  20. //getters,willbecalledbyusers
  21. /**GetthecorrespondingHttpRequestobjectwhichleadstothisresponse
  22. There'snopairedsetterforit,cozit'salreadysettedinclassconstructor
  23. inlineCCHttpRequest*getHttpRequest()
  24. return_pHttpRequest;
  25. /**Toseeifthehttpreqeustisreturnedsuccessfully,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Althroughuserscanjudgeif(httpreturncode=200),wewantaneasierway
  26. Ifthisgetterreturnsfalse,youcancallgetResponseCodeandgetErrorBuffertofindmoredetails
  27. inlineboolisSucceed()
  28. return_succeed;
  29. /**Getthehttpresponserawdata*/
  30. inlinestd::vector<char>*getResponseData()
  31. return&_responseData;
  32. /**GetthehttpresponseerrorCode
  33. *Iknowthatyouwanttoseehttp200:)
  34. inlineintgetResponseCode()
  35. return_responseCode;
  36. /**Gettherrorbufferwhichwilltellyoumoreaboutthereasonwhyhttprequestfailed
  37. inlineconstchar*getErrorBuffer()
  38. return_errorBuffer.c_str();
  39. //setters,willbecalledbyCCHttpClient
  40. //usersshouldavoidinvokingthesemethods
  41. /**Setifthehttprequestisreturnedsuccessfully,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Althroughuserscanjudgeif(httpcode==200),wewantaeasierway
  42. ThissetterismainlyusedinCCHttpClient,usersmustn'tsetitdirectly
  43. inlinevoidsetSucceed(boolvalue)
  44. _succeed=value;
  45. /**Setthehttpresponserawbuffer,isusedbyCCHttpClient
  46. inlinevoidsetResponseData(std::vector<char>*data)
  47. _responseData=*data;
  48. /**SetthehttpresponseerrorCode
  49. inlinevoidsetResponseCode(intvalue)
  50. _responseCode=value;
  51. /**Settheerrorbufferwhichwilltellyoumorethereasonwhyhttprequestfailed
  52. inlinevoidsetErrorBuffer(constchar*value)
  53. _errorBuffer.assign(value);
  54. boolinitWithRequest(CCHttpRequest*request);
  55. //这里要留意下,每个response中都会包含对应的request,所以能在数据处理回调函数中,获取我们在设置request的所有参数,比如像tag,userdata
  56. CCHttpRequest*_pHttpRequest;///thecorrespondingHttpRequestpointerwholeadstothisresponse
  57. bool_succeed;///toindecateifthehttpreqeustissuccessfulsimply
  58. std::vector<char>_responseData;///thereturnedrawdata.Youcanalsodumpitasastring
  59. int_responseCode;///thestatuscodereturnedfromlibcurl,e.g.200,404
  60. std::string_errorBuffer;///if_responseCode!=200,pleaseread_errorBuffertofindthereason
  61. };

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

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

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

(编辑:李大同)

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

    推荐文章
      热点阅读