您的位置:首页 > 理论基础 > 计算机网络

Cocos2d-x3.1 HttpClient封装与使用

2014-09-13 22:17 549 查看

1、首先给出封装后的工具类:HttpManager

#include "cocos2d.h"
#include "../cocos2d/extensions/cocos-ext.h"
#include "network/HttpClient.h"
USING_NS_CC;
USING_NS_CC_EXT;
using namespace network;
class  HTTPManagerDelegate
{
public:
virtual void onHttpManagerRequestCompleted(cocos2d::network::HttpClient *sender, cocos2d::network::HttpResponse *response) = 0;
};

class HTTPManager:public Ref
{
public:
HTTPManager();
~HTTPManager();
CC_SYNTHESIZE(HTTPManagerDelegate*, _httpManagerDelegate, HttpDelegate);
//Http Response Callback
void onHttpRequestCompleted(cocos2d::network::HttpClient *sender, cocos2d::network::HttpResponse *response);
void getFormData(std::string parameter);
void sendGetRequest(std::string url,std::string requestTag);
void writeFileFromRequest(cocos2d::network::HttpResponse *response,std::string filename);
typedef std::function<void(cocos2d::network::HttpClient *sender, cocos2d::network::HttpResponse *response)> ccHttpManagerCallback;
void addHttpListener(ccHttpManagerCallback& callback);

private:
ccHttpManagerCallback _eventCallback;
};

#include "HTTPManager.h"
#include <iostream>

//#include "../UnZip/DJZipArchive.h"
#define HTTPHeader "http://www.epicc.com.cn/QrDmzBastionNB/BastionServlet"

HTTPManager::HTTPManager()
{
}
HTTPManager::~HTTPManager()
{
}
void HTTPManager::sendGetRequest(std::string url,std::string requestTag)
{
HttpRequest* request = new HttpRequest();//使用HttpRequest无参的构造函数,提供了一个很好的默认设置
request->setRequestType(cocos2d::network::HttpRequest::Type::GET);//设置连接方式,常用GET和POST
request->setUrl(url.c_str());//设置连接地址
//设置回调,在onHttpRequestCompleted中读取数据
request->setResponseCallback(CC_CALLBACK_2(HTTPManager::onHttpRequestCompleted, this));
request->setTag(requestTag.c_str());//设置Tag
network::HttpClient::getInstance()->send(request);//添加到HttpClient任务队列
request->release();//释放连接
}

void HTTPManager::getFormData(std::string parameter)
{
HttpRequest* request = new HttpRequest();
request->setUrl(HTTPHeader);
request->setRequestType(HttpRequest::Type::POST);

request->setResponseCallback(CC_CALLBACK_2(HTTPManager::onHttpRequestCompleted, this));

//write the post data
const char* postData = StringUtils::format("parameter=%s",parameter.c_str()).c_str();
log("postData = %s",postData);
request->setRequestData(postData, strlen(postData));
request->setTag("getFormData");
log("url = %s",request->getUrl());

HttpClient::getInstance()->send(request);
request->release();
}

void HTTPManager::onHttpRequestCompleted(cocos2d::network::HttpClient *sender, cocos2d::network::HttpResponse *response)
{
if (!response) {
return;
}

if (0 != strlen(response->getHttpRequest()->getTag())) {
log("%s compeled",response->getHttpRequest()->getTag());
}

long statusCode = response->getResponseCode();

char statusString[64] = {};

sprintf(statusString, "HTTP Status Code:%ld , tag = %s",statusCode,response->getHttpRequest()->getTag());
log("response code:%s",statusString);

if (!response->isSucceed()) {
log("response failed");
log("error buffer:%s",response->getErrorBuffer());
return;
}

if (_httpManagerDelegate) {
_httpManagerDelegate->onHttpManagerRequestCompleted(sender, response);
}

const char* resTag = response->getHttpRequest()->getTag();
}

void HTTPManager::writeFileFromRequest(cocos2d::network::HttpResponse *response,std::string filename)
{

std::vector<char>* buffer = response->getResponseData();
printf("Http Test,dump data:");
std::string path= FileUtils::getInstance()->getWritablePath();
std::string fullPath =  path + filename;
FILE* fp = fopen(fullPath.c_str(), "wb");

log("将文件写入本地 %s",fullPath.c_str());

unsigned char bf;
for (unsigned int i  = 0; i < buffer->size(); i++) {

bf = buffer->at(i);
fwrite(&bf, 1, 1, fp);

}
fclose(fp);

}

void HTTPManager::addHttpListener(ccHttpManagerCallback &callback)
{
_eventCallback = callback;

}


        为提高代码可用性,此处一些方法接口并没用到,但是以防以后用到,还是贴了出来,下面看看使用实例。

2、使用实例

        使用类需继承HttpManagerDelegate,用来委托事件。

#include "cocos2d.h"
#include "HTTPManager.h"
USING_NS_CC;

class HelloWorld : public cocos2d::Layer,public HTTPManagerDelegate
{
public:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene();

// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();

// a selector callback
void menuCloseCallback(cocos2d::Ref* pSender);

virtual void onHttpManagerRequestCompleted(cocos2d::network::HttpClient *sender, cocos2d::network::HttpResponse *response) ;

void writeFileFromRequest(cocos2d::network::HttpResponse *response,std::string filename);

// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
};

#include "HelloWorldScene.h"
#include "HTTPManager.h"
USING_NS_CC;

Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();

// 'layer' is an autorelease object
auto layer = HelloWorld::create();

// add layer as a child to scene
scene->addChild(layer);

// return the scene
return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
}

Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();

/////////////////////////////
// 2. add a menu item with "X" image, which is clicked to quit the program
//    you may modify it.

// add a "close" icon to exit the progress. it's an autorelease object
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));

closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
origin.y + closeItem->getContentSize().height/2));

// create menu, it's an autorelease object
auto menu = Menu::create(closeItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu, 1);

auto httpManager = new HTTPManager();
httpManager->retain();
httpManager->setHttpDelegate(this);
httpManager->sendGetRequest("localhost:8080/qwe.json", "update_time");
return true;
}

void HelloWorld::onHttpManagerRequestCompleted(cocos2d::network::HttpClient *sender, cocos2d::network::HttpResponse *response)
{
if (strcmp(response->getHttpRequest()->getTag(), "update_time") == 0)
{
writeFileFromRequest(response,"qwe.json");
log("下载更新包");
std::string version = "version";
std::string table = "version";
if (!(strcmp(version.c_str(), table.c_str()) == 0))
{
log("下载更新包");
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

#endif
}

}

if (strcmp(response->getHttpRequest()->getTag(), "update_mobile") == 0)
{

log("update_mobile");
}

}

void HelloWorld::writeFileFromRequest(cocos2d::network::HttpResponse *response,std::string filename)
{
std::vector<char>* buffer = response->getResponseData();
printf("Http Test,dump data:");
std::string path= FileUtils::getInstance()->getWritablePath();
std::string fullPath =  path + filename;
FILE* fp = fopen(fullPath.c_str(), "wb");

log("将文件写入本地 %s",fullPath.c_str());
//    auto size = buffer->size();
//    unsigned char bf[size];
//    fwrite(bf, size, 1, fp);

unsigned char bf;
for (unsigned int i  = 0; i < buffer->size(); i++) {

bf = buffer->at(i);
fwrite(&bf, 1, 1, fp);

}
fclose(fp);

}

void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
return;
#endif

Director::getInstance()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}


3、使用类

        只要继承HttpManagerDelegate委托,即可实现函数的回调。其次,需要搭建服务器。关于函数的委托回调,前面有研究。

        (1)设置两个参数setHttpManagerDelegate(this),方便回调该HelloWorld类的onHttpManagerRequestCompleted函数

        (2)设置setGetRequest();第一个参数是URL,第二个是Tag。

4、流程

Eclipse ADT 导入HttpServer工程,运行,就可运行服务器。

关闭网络链接。

运行cocos2d-x工程

在网页地址栏输入:localhost:8080/文件名

注意:保存文件的后台路径需要自己修改

源码链接:http://download.csdn.net/user/yuxikuo_1/uploads
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Cocos2d-x3.1 HttpClient