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

cocos2d-x学习篇之网络(http)篇,第1张

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

这段时间接触到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:

[cpp] view plain copy //get请求 voIDhttpClIEntTest::onMenuGetTestClicked(cocos2d::CCObject*sender) { //test1 CChttpRequest*request=newCChttpRequest();//创建request对象,这里new出来的对象不能使用autorelease(),原因后述 request->setUrl("http://just-make-this-request-Failed.com");//设置url request->setRequestType(CChttpRequest::khttpGet);//设置请求方式 request->setResponseCallback(this,callfuncND_selector(httpClIEntTest::onhttpRequestCompleted));//这是回调对象和回调函数 request->setTag("GETtest1");//设置用户标识,可以通过response获取 CChttpClIEnt::getInstance()->send(request);//使用CChttpClIEnt共享实例来发送request request->release();//调用release() } //waiting m_labelStatusCode->setString("waiting..."); } //这里就是我们要处理接收到数据的回调函数了,sender为CChttpClIEnt实例指针,data为接收到的response指针 voIDhttpClIEntTest::onhttpRequestCompleted(cocos2d::CCNode*sender,voID*data) CChttpResponse*response=(CChttpResponse*)data; if(!response) return; //获取对应request的字符串标识 if(0!=strlen(response->gethttpRequest()->getTag())) cclog("%scompleted",response->gethttpRequest()->getTag()); //获取返回代码,比如200、404等 intstatusCode=response->getResponseCode(); charstatusstring[64]={}; sprintf(statusstring,"httpStatusCode:%d,tag=%s",statusCode,response->gethttpRequest()->getTag()); m_labelStatusCode->setString(statusstring); cclog("responsecode:%d",statusCode); if(!response->isSucceed()) { cclog("responseFailed"); cclog("errorbuffer:%s",response->getErrorBuffer());//可以调用getErrorBuffer()来获取错误原因 return; //dumpdata std::vector<char>*buffer=response->getResponseData();//用来获取接收到的数据 printf("httpTest,dumpdata:"); for(unsignedinti=0;i<buffer->size();i++) printf("%c",(*buffer)[i]); printf("\n"); }

基本上一个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 public: /**请求类型枚举,可以通过setReqeustType(param)设置*/ typedefenum khttpGet, khttpPost, khttpUnkown,248)"> }httpRequestType; /**Constructor BecausehttpRequestobjectwillbeusedbetweenUItheadandnetworkthread, requestObj->autorelease()isforbIDdentoavoIDcrashesinCCautoreleasePool new/retain/releasestillworks,whichmeansyouneedtoreleaseitmanually PleaserefertohttpRequestTest.cpptofinditsusage 这里是有注释的,因为要跨线程,所以就不能用autorelease() 我们在使用httpRequest的时候,需要自己new,然后再release下就可以了 当我们把httpRequest传递给CChttpClIEnt的时候,CChttpClIEnt已经帮我们retain了 工作线程中,需要使用CChttpRequest对象new一个CChttpResponse,CChttprequest会retain一次,所以工作线程也会release一次 具体的后文有 */ CChttpRequest() _requestType=khttpUnkown; _url.clear(); _requestData.clear(); _tag.clear(); _pTarget=NulL; _pSelector=NulL; _pUserData=NulL; }; virtual~CChttpRequest() if(_pTarget) _pTarget->release(); /**重载autorelease函数,禁止调用*/ CCObject*autorelease(voID) CCAssert(false,"httpResponseisusedbetweennetworkthreadanduithread\ therefore,autoreleaseisforbIDdenhere"); returnNulL; //setter/gettersforpropertIEs /**设置请求类型 目前支持khttpGet和khttpPost inlinevoIDsetRequestType(httpRequestTypetype) _requestType=type; /**返回请求类型*/ inlinehttpRequestTypegetRequestType() return_requestType; }; /**设置请求url voIDsetUrl(constchar*url) _url=url; /**获取请求url*/ char*getUrl() return_url.c_str(); /**这个设置用于post方式的data数据 voIDsetRequestData(char*buffer,unsignedintlen) _requestData.assign(buffer,buffer+len); /**Gettherequestdatapointerback*/ inlinechar*getRequestData() return&(_requestData.front()); /**Getthesizeofrequestdataback*/ intgetRequestDataSize() return_requestData.size(); /**为每个请求设置一个字符串标示,可以通过httpResponse->gethttpRequest->getTag()获取,因为httpResponse会将对应的httpRequest封装在里面 */ voIDsetTag(char*tag) _tag=tag; /**GetthestringtagbacktoIDentifytherequest. ThebestpracticeistouseitinyourMyClass::onMyhttpRequestCompleted(sender,httpResponse*)callback char*getTag() return_tag.c_str(); /**OptionfIEld.Youcanattachacustomeddataineachrequest,andgetitbackinresponsecallback. Butyouneedtonew/deletethedatapointermanully voIDsetUserData(voID*pUserData) _pUserData=pUserData; /**Getthepre-settedcustomdatapointerback. Don'tforgettodeleteit.httpClIEnt/httpResponse/httpRequestwilldonothingwiththispointer voID*getUserData() return_pUserData; /**通过这个函数设置我们的数据处理回调函数 voIDsetResponseCallback(CCObject*pTarget,SEL_CallFuncNDpSelector) _pTarget=pTarget; _pSelector=pSelector; _pTarget->retain(); /**Getthetargetofcallbackselectorfuntion,mainlyusedbyCChttpClIEnt*/ inlineCCObject*getTarget() return_pTarget; /**Gettheselectorfunctionpointer,mainlyusedbyCChttpClIEnt*/ inlineSEL_CallFuncNDgetSelector() return_pSelector; /**Setanycustomheaders**/ voIDsetheaders(std::vector<std::string>pheaders) _headers=pheaders; /**Getcustomheaders**/ inlinestd::vector<std::string>getheaders() return_headers; protected: //propertIEs httpRequestType_requestType;///请求方式 std::string_url;///请求url char>_requestData;///用于POST std::string_tag;///用户自定义标识,可以用来在response回调中区分request CCObject*_pTarget;///回调对象 SEL_CallFuncND_pSelector;///回调函数例如MyLayer::onhttpResponse(CCObject*sender,voID*data) voID*_pUserData;///用户自定义数据,和_tag用法一样,只不过是用途不一样 std::vector<std::string>_headers;///customhttpheaders };
httpResponse.h,这个文件和httpRequest差不多,没什么好说的
copy classCChttpResponse:/**Constructor,it'susedbyCChttpClIEntinternal,usersdon'tneedtocreatehttpResponsemanually @paramrequestthecorrespondinghttpRequestwhichleadstothisresponse CChttpResponse(CChttpRequest*request) _phttpRequest=request; if(_phttpRequest) _phttpRequest->retain(); _succeed=false; _responseData.clear(); _errorBuffer.clear(); /**Destructor,itwillbecalledinCChttpClIEntinternal, usersdon'tneedtodesturcthttpResponSEObjectmanully virtual~CChttpResponse() if(_phttpRequest) _phttpRequest->release(); /**OverrIDeautoreleasemethodtopreventdevelopersfromcallingit*/ CCObject*autorelease(voID) CCAssert(thread\ therefore,autoreleaseisforbIDdenhere"); returnNulL; //getters,willbecalledbyusers /**GetthecorrespondinghttpRequestobjectwhichleadstothisresponse There'snopairedsetterforit,cozit'salreadysettedinclassconstructor inlineCChttpRequest*gethttpRequest() return_phttpRequest; /**Toseeifthehttpreqeustisreturnedsuccessfully,0); background-color:inherit">Althroughuserscanjudgeif(httpreturncode=200),wewantaneasIErway Ifthisgetterreturnsfalse,youcancallgetResponseCodeandgetErrorBuffertofindmoredetails boolisSucceed() return_succeed; /**Getthehttpresponserawdata*/ inlinestd::vector<char>*getResponseData() return&_responseData; /**GetthehttpresponseerrorCode *IkNowthatyouwanttoseehttp200:) intgetResponseCode() return_responseCode; /**GettherrorbufferwhichwilltellyoumoreaboutthereasonwhyhttprequestFailed char*getErrorBuffer() return_errorBuffer.c_str(); //setters,willbecalledbyCChttpClIEnt //useRSShouldavoIDinvokingthesemethods /**Setifthehttprequestisreturnedsuccessfully,0); background-color:inherit">Althroughuserscanjudgeif(httpcode==200),wewantaeasIErway ThissetterismainlyusedinCChttpClIEnt,usersmustn'tsetitdirectly voIDsetSucceed(boolvalue) _succeed=value; /**Setthehttpresponserawbuffer,isusedbyCChttpClIEnt voIDsetResponseData(std::vector<char>*data) _responseData=*data; /**SetthehttpresponseerrorCode voIDsetResponseCode(intvalue) _responseCode=value; /**SettheerrorbufferwhichwilltellyoumorethereasonwhyhttprequestFailed voIDsetErrorBuffer(char*value) _errorBuffer.assign(value); boolinitWithRequest(CChttpRequest*request); //这里要留意下,每个response中都会包含对应的request,所以能在数据处理回调函数中,获取我们在设置request的所有参数,比如像tag,userdata CChttpRequest*_phttpRequest;///thecorrespondinghttpRequestpointerwholeadstothisresponse bool_succeed;///toindecateifthehttpreqeustissuccessfulsimply std::vector<char>_responseData;///thereturnedrawdata.Youcanalsodumpitasastring int_responseCode;///thestatuscodereturnedfromlibcurl,e.g.200,404 std::string_errorBuffer;///if_responseCode!=200,pleaseread_errorBuffertofindthereason };
说白了,CChttpRequest和CChttpResponse只不过是发送队列中的数据类型,和接收队列中的数据类型,是线程之间传递的参数,下面来说说CChttpClIEnt
httpClIEnt.h

copy //CChttpClIEnt是一个单例模式的类,整个程序共享一个实例对象 classCChttpClIEnt:publicCCObject public: /**获取共享的单例对象**/ staticCChttpClIEnt*getInstance(); /**Relasethesharedinstance**/ staticvoIDdestroyInstance(); /** *Addagetrequesttotaskqueue *@paramrequestaCChttpRequestobject,whichincludesurl,responsecallbacketc. pleasemakesurerequest->_requestDataisclearbeforecalling"send"here. *@returnNulL voIDsend(CChttpRequest*request); /** *Changetheconnecttimeout *@paramtimeout voIDsetTimeoutForConnect(intvalue){_timeoutForConnect=value;}; *Getconnecttimeout *@returnint * intgetTimeoutForConnect(){return_timeoutForConnect;} *Changethedownloadtimeout *@paramvalue *@returnNulL voIDsetTimeoutForRead(intvalue){_timeoutForRead=value;}; *Getdownloadtimeout intgetTimeoutForRead(){return_timeoutForRead;}; private: CChttpClIEnt(); virtual~CChttpClIEnt(); boolinit(voID); *Initpthreadmutex,semaphore,andcreatenewthreadforhttprequests *@returnbool boollazyInitThreadSemphore(); /**Pollfunctioncalledfrommainthreadtodispatchcallbackswhenhttprequestsfinished**/ voIDdispatchResponseCallbacks(floatdelta); private: int_timeoutForConnect;//连接超时时间 int_timeoutForRead;//接收数据超时时间 //std::stringreqID; };


httpClIEnt.cpp

copy staticpthread_ts_networkThread;//工作线程句柄 staticpthread_mutex_ts_requestQueueMutex;//请求队列互斥变量 staticpthread_mutex_ts_responseQueueMutex;//接收队列互斥变量 staticsem_t*s_pSem=NulL;//用来驱动线程工作的信号量 staticunsignedlongs_asyncRequestCount=0;//当前需要处理的request个数 #ifCC_TARGET_PLATFORM==CC_PLATFORM_IOS #defineCC_ASYNC_httpREQUEST_USE_nameD_SEMAPHORE1 #else #defineCC_ASYNC_httpREQUEST_USE_nameD_SEMAPHORE0 #endif #ifCC_ASYNC_httpREQUEST_USE_nameD_SEMAPHORE #defineCC_ASYNC_httpREQUEST_SEMAPHORE"cchttpAsync" staticsem_ts_sem; #if(CC_TARGET_PLATFORM==CC_PLATFORM_WIN32) typedefintint32_t; staticboolneed_quit=false;//退出标识 staticCCArray*s_requestQueue=NulL;//请求队列(下面都说request队列) staticCCArray*s_responseQueue=NulL;//接收队列(下面都说response队列) staticCChttpClIEnt*s_phttpClIEnt=NulL;//全局单例CChttpClIEnt对象 chars_errorBuffer[CURL_ERROR_SIZE];//错误提示buffer 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收到数据的回调函数 //这个便是当cURL接收到数据回调的函数,也就是在这里对response进行填充,这里的声明方式和fwrite()函数一样 size_twriteData(voID*stream) //ptr指向接受到的数据,sizes为字节数 //这里传过来的stream中保存了CChttpResponse::_responseData char>*recvBuffer=(std::vector<char>*)stream; size_tsizes=size*nmemb; //adddatatotheendofrecvBuffer //将接受到的数据写到response中去 recvBuffer->insert(recvBuffer->end(),(char*)ptr,(char*)ptr+sizes); returnsizes; //Prototypes boolconfigureCURL(CURL*handle); intprocessGetTask(CChttpRequest*request,write_callbackcallback,153); Font-weight:bold; background-color:inherit">voID*stream,int32_t*errorCode); intprocesspostTask(CChttpRequest*request,int32_t*errorCode); //intprocessDownloadTask(httpRequest*task,voID*stream,int32_t*errorCode); //工作线程 voID*networkThread( CChttpRequest*request=NulL; while(true) //等待主线程发送信号,就是调用send()函数 intsemWaitRet=sem_wait(s_pSem); if(semWaitRet<0){ cclog("httpRequestasyncthreadsemaphoreerror:%s\n",strerror(errno)); break; //退出 if(need_quit) break; //step1:sendhttprequestiftherequestQueueisn'tempty request=NulL; pthread_mutex_lock(&s_requestQueueMutex);//给request队列上锁 if(0!=s_requestQueue->count()) request=dynamic_cast<CChttpRequest*>(s_requestQueue->objectAtIndex(0));//取得第一个request s_requestQueue->removeObjectAtIndex(0);//将其移除队列 //这里的request的引用次数为1,因为只有在send()函数中retain了一次 pthread_mutex_unlock(&s_requestQueueMutex);//request队列解锁 if(NulL==request) continue; //同步调用cURL库 //使用request来创建一个response CChttpResponse*response=newCChttpResponse(request); //在CChttpTtpResponse构造中,会将request再retain一次 request->release(); //这里,只有response中有request的一次引用计数 intresponseCode=-1; intretValue=0; //根据请求类型设置cURL参数 switch(request->getRequestType()) caseCChttpRequest::khttpGet://httpGET 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); caseCChttpRequest::khttpPost://httpPOST 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); default: true,"CChttpClIEnt:unkownrequesttype,onlyGETandPOStaresupported"); //设置返回代码 response->setResponseCode(responseCode); if(retValue!=0) response->setSucceed(false); response->setErrorBuffer(s_errorBuffer); else response->setSucceed(true); //将response加入队列 pthread_mutex_lock(&s_responseQueueMutex);//给response加锁 s_responseQueue->addobject(response); pthread_mutex_unlock(&s_responseQueueMutex);//解锁 //启动CCScheduler调度 CCDirector::sharedDirector()->getScheduler()->resuMetarget(CChttpClIEnt::getInstance()); //线程退出,清理request队列 pthread_mutex_lock(&s_requestQueueMutex); s_requestQueue->removeAllObjects(); pthread_mutex_unlock(&s_requestQueueMutex); s_asyncRequestCount-=s_requestQueue->count(); if(s_pSem!=NulL){ sem_unlink(CC_ASYNC_httpREQUEST_SEMAPHORE); sem_close(s_pSem); #else sem_destroy(s_pSem); #endif s_pSem=NulL; //释放互斥变量 pthread_mutex_destroy(&s_requestQueueMutex); pthread_mutex_destroy(&s_responseQueueMutex); s_requestQueue->release(); s_responseQueue->release(); pthread_exit(NulL); return0; //设置cURL超时属性 boolconfigureCURL(CURL*handle) if(!handle){ returnfalse; int32_tcode; //设置错误信息缓冲 code=curl_easy_setopt(handle,CURLOPT_ERRORBUFFER,s_errorBuffer); if(code!=CURLE_OK){ //设置超时时间 code=curl_easy_setopt(handle,CURLOPT_TIMEOUT,CChttpClIEnt::getInstance()->getTimeoutForRead()); if(code!=CURLE_OK){ true; //处理get方式请求 //stream传递过来的是response->getResponseData() //关于cURL的东西这里就不多说了 int*responseCode) CURLcodecode=CURL_LAST; //初始化cURL CURL*curl=curl_easy_init(); do{ if(!configureCURL(curl))//配置cURL /*handlecustomheaderdata*/ /*createcurllinkedList*/ structcurl_sList*cheaders=NulL; /*getcustomheaderdata(ifset)*/ std::vector<std::string>headers=request->getheaders(); if(!headers.empty()) for(std::vector<std::string>::iteratorit=headers.begin();it!=headers.end();it++) /*appendcustomheadersonebyone*/ cheaders=curl_sList_append(cheaders,it->c_str()); /*setcustomheadersforcurl*/ code=curl_easy_setopt(curl,CURLOPT_httpheader,cheaders); if(code!=CURLE_OK) //这里将response->_responseData设置为cURL回调函数中的stream参数 code=curl_easy_perform(curl); /*freethelinkedListforheaderdata*/ curl_sList_free_all(cheaders); code=curl_easy_getinfo(curl,CURliNFO_RESPONSE_CODE,responseCode); if(code!=CURLE_OK||*responseCode!=200) code=CURLE_http_RETURNED_ERROR; }while(0); if(curl){ curl_easy_cleanup(curl); return(code==CURLE_OK?0:1); //这个就不说了,其实都一样的,cURL承担了所有工作 CURLcodecode=CURL_LAST; if(!configureCURL(curl)){ /*handlecustomheaderdata*/ /*createcurllinkedList*/ structcurl_sList*cheaders=NulL; /*getcustomheaderdata(ifset)*/ std::vector<std::string>headers=request->getheaders(); if(!headers.empty()) for(std::vector<std::string>::iteratorit=headers.begin();it!=headers.end();it++) /*appendcustomheadersonebyone*/ cheaders=curl_sList_append(cheaders,it->c_str()); /*setcustomheadersforcurl*/ code=curl_easy_setopt(curl,cheaders); code=curl_easy_perform(curl); if(code!=CURLE_OK||*responseCode!=200){ code=CURLE_http_RETURNED_ERROR; }while(0); //返回共享实例 CChttpClIEnt*CChttpClIEnt::getInstance() if(s_phttpClIEnt==NulL){ s_phttpClIEnt=newCChttpClIEnt(); returns_phttpClIEnt; voIDCChttpClIEnt::destroyInstance() CCAssert(s_phttpClIEnt,""); //将CChttpClIEnt::dispatchResponseCallbacks()函数从CCShecduler中取消挂载 CCDirector::sharedDirector()->getScheduler()->unscheduleSelector(schedule_selector(CChttpClIEnt::dispatchResponseCallbacks),s_phttpClIEnt); s_phttpClIEnt->release(); CChttpClIEnt::CChttpClIEnt() :_timeoutForConnect(30) ,_timeoutForRead(60) //将成员函数dispatchTesponseCallbacks()挂载至CCSheduler CCDirector::sharedDirector()->getScheduler()->scheduleSelector( schedule_selector(CChttpClIEnt::dispatchResponseCallbacks),false); //初始化为停止调度,由工作线程接收到了数据之后启用调度 CCDirector::sharedDirector()->getScheduler()->pauseTarget(this); CChttpClIEnt::~CChttpClIEnt() need_quit=true; sem_post(s_pSem); s_phttpClIEnt=NulL; //只有在第一次调用send()时调用,去初始化队列、创建线程、初始化互斥变量等 boolCChttpClIEnt::lazyInitThreadSemphore() else{ s_pSem=sem_open(CC_ASYNC_httpREQUEST_SEMAPHORE,O_CREAT,0644,0); if(s_pSem==SEM_Failed){ cclog("OpenhttpRequestSemaphoreFailed"); s_pSem=NulL; intsemRet=sem_init(&s_sem,0); if(semRet<0){ cclog("InithttpRequestSemaphoreFailed"); s_pSem=&s_sem; s_requestQueue=newCCArray(); s_requestQueue->init(); s_responseQueue=newCCArray(); s_responseQueue->init(); pthread_mutex_init(&s_requestQueueMutex,NulL); pthread_mutex_init(&s_responseQueueMutex,NulL); pthread_create(&s_networkThread,NulL,networkThread,248)"> pthread_detach(s_networkThread); //Addagettasktoqueue voIDCChttpClIEnt::send(CChttpRequest*request) //第一次调用的时候初始化 if(false==lazyInitThreadSemphore()) if(!request) //将当前需要处理的request个数++ ++s_asyncRequestCount; //在这里对request进行第一次retain, request->retain(); //这里request的引用次数为1 pthread_mutex_lock(&s_requestQueueMutex);//request队列加锁 s_requestQueue->addobject(request);//push到request队列 //发送信号唤醒工作线程 //将response队列数据分发 voIDCChttpClIEnt::dispatchResponseCallbacks(floatdelta) //cclog("CChttpClIEnt::dispatchResponseCallbacksisrunning"); CChttpResponse*response=NulL; pthread_mutex_lock(&s_responseQueueMutex);//给response队列上锁 if(s_responseQueue->count()) response=dynamic_cast<CChttpResponse*>(s_responseQueue->objectAtIndex(0));//取出response s_responseQueue->removeObjectAtIndex(0);//将其从response队列移除 pthread_mutex_unlock(&s_responseQueueMutex);//解锁 if(response) --s_asyncRequestCount; CChttpRequest*request=response->gethttpRequest(); CCObject*pTarget=request->getTarget();//获取request回调函数的对象 SEL_CallFuncNDpSelector=request->getSelector();//获取回调函数 if(pTarget&&pSelector) (pTarget->*pSelector)((CCNode*)//调用回调函数,并把本单例对象和response传递给我们设置在request中的回调函数 response->release(); if(0==s_asyncRequestCount)//如果没有没有请求,停止调度 }

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

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

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

总结

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

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1010604.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存