Cocos2d-x   发布时间:2022-05-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了cocos2d-x学习篇之网络(http)篇大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

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

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

Cocos2dx 为我们封装了在cocos2dx中http的网络框架,其文件在cocos2dx引擎包的cocos2d-2.1rc0-x-2.1.2\extensions\network文件下的 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:

  1. //get请求
  2. @H_673_60@ 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. @H_963_53@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. @H_963_53@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,其实这个文件没什么好说的,都有注释

@H_616_398@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. //usersshouldavoidinvokingtheseR_300_11845@ethods
  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 @H_568_1717@

    //CChttpClient是一个单例模式的类,整个程序共享一个实例对象
  1. classCChttpClient:publicCCObject
  2. public:
  3. /**获取共享的单例对象**/
  4. staticCChttpClient*geTinstance();
  5. /**Relasethesharedinstance**/
  6. staticvoiddestroyInstance();
  7. /**
  8. *Addagetrequest@R_795_10586@skqueue
  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

@H_616_398@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:%s\n",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. :rgb(108,CURLOPT_CONNECTTIMEOUT,CChttpClient::geTinstance()->getTimeoutForConnect());
  119. returntrue;
  120. //处理get方式请求
  121. //stream传递过来的是response->getResponseData()
  122. //关于cURL的东西这里就不多说了
  123. intprocessGetTask(CChttprequest*request,int*responseCodE)
  124. CURLcodecode=CURL_LAST;
  125. //初始化cURL
  126. CURL*curl=curl_easy_init();
  127. do{
  128. if(!configureCURL(curl))//配置cURL
  129. /*handlecustomheaderdata*/
  130. /*createcurllinkedlist*/
  131. structcurl_slist*cHeaders=NULL;
  132. /*getcustomheaderdata(ifset)*/
  133. std::vector<std::string>headers=request->getHeaders();
  134. if(!headers.empty())
  135. for(std::vector<std::string>::iteratorit=headers.begin();it!=headers.end();it++)
  136. /*appendcustomheadersonebyone*/
  137. cHeaders=curl_slist_append(cHeaders,it->c_str());
  138. /*setcustomheadersforcurl*/
  139. code=curl_easy_setopt(curl,CURLOPT_httpHEADER,cHeaders);
  140. :rgb(108,CURLOPT_URL,request->getUrl());
  141. if(code!=CURLE_OK)
  142. :rgb(108,CURLOPT_FOLLOWLOCATION,CURLOPT_WRITEFUNCTION,callBACk);
  143. //这里将response->_responseData设置为cURL回调函数中的stream参数
  144. :rgb(108,CURLOPT_WRITEDATA,stream);
  145. code=curl_easy_perform(curl);
  146. /*freetHelinkedlistforheaderdata*/
  147. curl_slist_free_all(cHeaders);
  148. code=curl_easy_geTinfo(curl,CURLINFO_RESPONSE_CODE,responseCodE);
  149. if(code!=CURLE_OK||*responseCode!=200)
  150. code=CURLE_http_RETURNED_ERROR;
  151. }while(0);
  152. if(curl){
  153. curl_easy_cleanup(curl);
  154. return(code==CURLE_OK?0:1);
  155. //这个就不说了,其实都一样的,cURL承担了所有工作
  156. intprocessPostTask(CChttprequest*request,int32_t*responseCodE)
  157. CURLcodecode=CURL_LAST;
  158. if(!configureCURL(curl)){
  159. /*handlecustomheaderdata*/
  160. /*createcurllinkedlist*/
  161. structcurl_slist*cHeaders=NULL;
  162. /*getcustomheaderdata(ifset)*/
  163. std::vector<std::string>headers=request->getHeaders();
  164. if(!headers.empty())
  165. for(std::vector<std::string>::iteratorit=headers.begin();it!=headers.end();it++)
  166. /*appendcustomheadersonebyone*/
  167. cHeaders=curl_slist_append(cHeaders,it->c_str());
  168. /*setcustomheadersforcurl*/
  169. code=curl_easy_setopt(curl,cHeaders);
  170. :rgb(108,request->getUrl());
  171. :rgb(108,callBACk);
  172. :rgb(108,stream);
  173. :rgb(108,CURLOPT_POST,1);
  174. :rgb(108,CURLOPT_POSTFIELDS,request->getrequestData());
  175. :rgb(108,CURLOPT_POSTFIELDSIZE,request->getrequestDataSize());
  176. code=curl_easy_perform(curl);
  177. if(code!=CURLE_OK||*responseCode!=200){
  178. code=CURLE_http_RETURNED_ERROR;
  179. }while(0);
  180. //返回共享实例
  181. CChttpClient*CChttpClient::geTinstance()
  182. if(s_phttpClient==NULL){
  183. s_phttpClient=newCChttpClient();
  184. returns_phttpClient;
  185. voidCChttpClient::destroyInstance()
  186. CCassert(s_phttpClient,"");
  187. //将CChttpClient::dispatchResponseCallBACks()函数从CCShecduler中取消挂载
  188. CCDirector::sharedDirector()->getscheduler()->unscheduleSELEctor(schedule_SELEctor(CChttpClient::dispatchResponseCallBACks),s_phttpClient);
  189. s_phttpClient->release();
  190. CChttpClient::CChttpClient()
  191. :_timeoutForConnect(30)
  192. ,_timeoutForRead(60)
  193. //将成员函数dispatchTesponseCallBACks()挂载至CCSheduler
  194. CCDirector::sharedDirector()->getscheduler()->scheduleSELEctor(
  195. schedule_SELEctor(CChttpClient::dispatchResponseCallBACks),this,false);
  196. //初始化为停止调度,由工作线程接收到了数据之后启用调度
  197. CCDirector::sharedDirector()->getscheduler()->pauseTarget(this);
  198. CChttpClient::~CChttpClient()
  199. need_quit=true;
  200. sem_post(s_pSem);
  201. s_phttpClient=NULL;
  202. //只有在第一次调用send()时调用,去初始化队列、创建线程、初始化互斥变量等
  203. boolCChttpClient::lazyInitThreadSemphore()
  204. }else{
  205. s_pSem=sem_open(CC_ASYNC_httprequEST_SEMAPHORE,O_CREAT,0644,0);
  206. if(s_pSem==SEM_FAILED){
  207. CCLog("OpenhttprequestSemaphorefailed");
  208. s_pSem=NULL;
  209. intsemRet=sem_init(&s_sem,0);
  210. if(semRet<0){
  211. CCLog("InithttprequestSemaphorefailed");
  212. s_pSem=&s_sem;
  213. s_requestQueue=newCCArray();
  214. s_requestQueue->init();
  215. s_responseQueue=newCCArray();
  216. s_responseQueue->init();
  217. pthread_mutex_init(&s_requestQueueMutex,null);
  218. pthread_mutex_init(&s_responseQueueMutex,null);
  219. pthread_create(&s_networkThread,NULL,networkThread,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> pthread_detach(s_networkThread);
  220. need_quit=false;
  221. //Addagettasktoqueue
  222. voidCChttpClient::send(CChttprequest*request)
  223. //第一次调用的时候初始化
  224. if(false==lazyInitThreadSemphore())
  225. if(!request)
  226. //将当前需要处理的request个数++
  227. ++s_asyncrequestCount;
  228. //在这里对request进行第一次retain,
  229. request->retain();
  230. //这里request的引用次数为1
  231. pthread_mutex_lock(&s_requestQueueMuteX);//request队列加锁
  232. s_requestQueue->addObject(request);//push到request队列
  233. pthread_mutex_unlock(&s_requestQueueMuteX);//解锁
  234. //发送信号唤醒工作线程
  235. //将response队列数据分发
  236. voidCChttpClient::dispatchResponseCallBACks(floatdelta)
  237. //CCLog("CChttpClient::dispatchResponseCallBACksisrunning");
  238. CChttpResponse*response=NULL;
  239. pthread_mutex_lock(&s_responseQueueMuteX);//给response队列上锁
  240. if(s_responseQueue->count())
  241. response=dynamic_cast<CChttpResponse*>(s_responseQueue->objectATindex(0));//取出response
  242. s_responseQueue->removeObjectATindex(0);//将其从response队列移除
  243. pthread_mutex_unlock(&s_responseQueueMuteX);//解锁
  244. if(responsE)
  245. --s_asyncrequestCount;
  246. CChttprequest*request=response->gethttprequest();
  247. CCObject*pTarget=request->getTarget();//获取request回调函数的对象
  248. SEL_CallFuncNDpSELEctor=request->getSELEctor();//获取回调函数
  249. if(pTarget&&pSELEctor)
  250. (pTarget->*pSELEctor)((CCNode*)this,responsE);//调用回调函数,并把本单例对象和response传递给我们设置在request中的回调函数
  251. response->release();
  252. if(0==s_asyncrequestCount)//如果没有没有请求,停止调度
  253. }

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

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

大佬总结

以上是大佬教程为你收集整理的cocos2d-x学习篇之网络(http)篇全部内容,希望文章能够帮你解决cocos2d-x学习篇之网络(http)篇所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:cocoscocos2ddhttpx学习网络
猜你在找的Cocos2d-x相关文章
其他相关热搜词更多
phpJavaPython程序员load如何string使用参数jquery开发安装listlinuxiosandroid工具javascriptcap