cocos2dx HTTP网络连接
简介
cocos2dx中HTTP网络连接部分主要使用了curl开源库。curl是一个跨平台的库,它可以模拟浏览器请求,模拟表单数据,上传下载,支持ftp和https,功能很强大,具体帮助信息可以通过curl的官网获取,http://curl.haxx.se/。它一般在PHP和C++中使用比较广泛。从官网下载下来的curl库,可以编译成工具,直接使用命令行方式运行,也可使用库文件在代码中调用。
cocos2dx中访问http网络有两种方式,一种就是直接使用curl库,自己构造相关参数,但前提是需要对curl使用方法有一定了解。还有一种就是使用HttpClient类,它是引擎基于curl为我们封装的一个类,使用起来比较方便,多线程,安全。两种方式区别在于HttpClient是异步的,而使用curl可以是同步的,也可以写成异步的,并且比较灵活,也可以应对比较复杂的网络请求。但一般情况下,建议直接使用HttpClient。
下面简单介绍一下curl的几个重要函数,知道了这几个函数的意义,使用起来就方便很多。使用时需要包含#include curl/curl.h
curl函数
1, CURLcode curl_global_init(long flags);
描述:从字面意思来看已经知道,这个函数只能调用一次。在模块的初始化函数中调用。
如果这个函数在curl_easy_init函数调用时还没调用,它将由libcurl库自动完成。
2, void curl_global_cleanup(void);
描述:在结束对libcurl调用的时候,也就是模块不再使用时,用来对curl_global_init做的清理工作。类似于close的函数。
3, char*curl_version( );
描述: 打印当前libcurl库的版本。
4 ,CURL*curl_easy_init( );
描述:curl_easy_init用来初始化一个CURL的指针(有些像返回FILE类型的指针一样). 相应的在调用结束时要用curl_easy_cleanup函数清理。一般curl_easy_init意味着一个连接的开始。
5,void curl_easy_cleanup(CURL*handle);
描述:这个调用用来结束一个连接。与curl_easy_init配合着用。参数就是init函数的返回值。
6,CURLcodecurl_easy_setopt(CURL *handle,CURLoption option,parameter);
描述: 这个函数是比较重要的一个,几乎所有的curl 程序都要频繁的使用它。
它告诉curl此次连接需要什么参数,例如请求类型,超时时间,是否支持SSL等。
CURLoption这个参数可以查找相应的头文件就可以知道curl支持哪些功能。
7 ,CURLcode curl_easy_perform(CURL*handle);
描述:执行当前的请求。需要在执行curl_easy_init和curl_easy_setopt之后运行,参数同样是初始化时的返回值,这个函数是一个阻塞函数,当收到网络响应时才会返回。因此如果想要使用异步方式访问网络,应该在另外的线程中调用此函数。
cocos2dx中使用curl示例程序
以下程序简单的访问了google.com网址,并设置了超时时间和在屏幕上显示服务器返回信息。
class CurlTest : public Layer { public: CurlTest(); ~CurlTest(); virtual void ccTouchesEnded(cocos2d::CCSet *pTouches,cocos2d::CCEvent *pEvent); private: cocos2d::CCLabelTTF* m_pLabel; }; CurlTest::CurlTest() { CCLabelTTF* label = CCLabelTTF::create("Curl Test","Arial",28); addChild(label,0); label->setPosition( ccp(VisibleRect::center().x,VisibleRect::top().y-50) ); setTouchEnabled(true); // create a label to display the tip string m_pLabel = CCLabelTTF::create("Touch the screen to connect",22); m_pLabel->setPosition(VisibleRect::center()); addChild(m_pLabel,0); m_pLabel->retain(); curl_global_init(CURL_GLOBAL_ALL); } void CurlTest::ccTouchesEnded(CCSet *pTouches,CCEvent *pEvent) { CURL *curl; CURLcode res; char buffer[10]; curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl,CURLOPT_URL,"google.com"); curl_easy_setopt(curl,CURLOPT_VERBOSE,TRUE); curl_easy_setopt(curl,CURLOPT_TIMEOUT,10); res = curl_easy_perform(curl); /* always cleanup */ curl_easy_cleanup(curl); if (res == 0) { m_pLabel->setString("0 response"); } else { sprintf(buffer,"code: %i",res); m_pLabel->setString(buffer); } } else { m_pLabel->setString("no curl"); } }
HttpClient接口
使用HttpClient比较简单,首先构造一个HttpRequest类,设置请求的url,请求类型等。HttpClient是一个单例,调用其send方法,把请求发送出去。然后在HttpRequest中设置的回调函数中获取HttpResponse对象即可。
<span style="white-space:pre"> </span>HttpRequest* request = new HttpRequest(); // required fields request->setUrl("http://httpbin.org/ip"); request->setRequestType(HttpRequest::Type::GET); request->setResponseCallback(CC_CALLBACK_2(HttpClientTest::onHttpRequestCompleted,this)); if (isImmediate) { request->setTag("GET immediate test2"); HttpClient::getInstance()->sendImmediate(request); }else { request->setTag("GET test2"); HttpClient::getInstance()->send(request); } // don't forget to release it,pair to new request->release();
void HttpClientTest::onHttpRequestCompleted(HttpClient *sender,HttpResponse *response) { if (!response) { return; } // You can get original request type from: response->request->reqType if (0 != strlen(response->getHttpRequest()->getTag())) { log("%s completed",response->getHttpRequest()->getTag()); } long statusCode = response->getResponseCode(); char statusString[64] = {}; sprintf(statusString,"HTTP Status Code: %ld,tag = %s",statusCode,response->getHttpRequest()->getTag()); _labelStatusCode->setString(statusString); log("response code: %ld",statusCode); if (!response->isSucceed()) { log("response Failed"); log("error buffer: %s",response->getErrorBuffer()); return; } // dump data std::vector<char> *buffer = response->getResponseData(); printf("Http Test,dump data: "); for (unsigned int i = 0; i < buffer->size(); i++) { printf("%c",(*buffer)[i]); } printf("\n"); if (response->getHttpRequest()->getReferenceCount() != 2) { log("request ref count not 2,is %d",response->getHttpRequest()->getReferenceCount()); } }