这段时间接触到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:
-
- voidHttpClientTest::onMenuGetTestClicked(cocos2d::CCObject*sender)
- {
-
- CCHttpRequest*request=newCCHttpRequest();
- request->setUrl("http://just-make-this-request-failed.com");//设置url
- request->setRequestType(CCHttpRequest::kHttpGet);
- request->setResponseCallback(this,callfuncND_selector(HttpClientTest::onHttpRequestCompleted));
- request->setTag("GETtest1");
- CCHttpClient::getInstance()->send(request);
- request->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());
- 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,其实这个文件没什么好说的,都有注释
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;
- char>_requestData;
- std::string_tag;
- CCObject*_pTarget;
- SEL_CallFuncND_pSelector;
- void*_pUserData;
- std::vector<std::string>_headers;
- };
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;
- bool_succeed;
- std::vector<char>_responseData;
- int_responseCode;
- std::string_errorBuffer;
- };
说白了,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
staticpthread_ts_networkThread;
- staticpthread_mutex_ts_requestQueueMutex;
- staticpthread_mutex_ts_responseQueueMutex;
- staticsem_t*s_pSem=NULL;
- staticunsignedlongs_asyncRequestCount=0;
- #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;
- staticCCArray*s_responseQueue=NULL;
- staticCCHttpClient*s_pHttpClient=NULL;
- chars_errorBuffer[CURL_ERROR_SIZE];
- 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接收到数据回调的函数,也就是在这里对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:%sn",strerror(errno));
- break;
- //退出
- if(need_quit)
- break;
- //step1:sendhttprequestiftherequestQueueisn'tempty
- request=NULL;
- pthread_mutex_lock(&s_requestQueueMutex);
- if(0!=s_requestQueue->count())
- request=dynamic_cast<CCHttpRequest*>(s_requestQueue->objectAtIndex(0));
- s_requestQueue->removeObjectAtIndex(0);
- //这里的request的引用次数为1,因为只有在send()函数中retain了一次
- pthread_mutex_unlock(&s_requestQueueMutex);
- 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:
- 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:
- 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);
- 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))
- /*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);
- s_requestQueue->addObject(request);
- //发送信号唤醒工作线程
- //将response队列数据分发
- voidCCHttpClient::dispatchResponseCallbacks(floatdelta)
- //CCLog("CCHttpClient::dispatchResponseCallbacksisrunning");
- CCHttpResponse*response=NULL;
- pthread_mutex_lock(&s_responseQueueMutex);
- if(s_responseQueue->count())
- response=dynamic_cast<CCHttpResponse*>(s_responseQueue->objectAtIndex(0));
- s_responseQueue->removeObjectAtIndex(0);
- pthread_mutex_unlock(&s_responseQueueMutex);
- if(response)
- --s_asyncRequestCount;
- CCHttpRequest*request=response->getHttpRequest();
- CCObject*pTarget=request->getTarget();
- 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,拜读大神的文章,所以就想着咱也来发表一遍学习心得吧,这样既可以提高自己,也可以和大家交流交流心得,更重要的是我发现写博客可以提升学习的兴趣
好了,就到这里了,以后有时间再继续
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|