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", "Arial", 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());
}
}