上篇使用python + tornado搭建了一个最简单的服务,现在我们在客户端连接下我们的服务器,实现client和server的通信。
一,环境
OS X 10.8.5 、XCode 5.1.1、cocos2dx 2.1rc0-x-2.1.4
二,cocos2dx的http请求
cocos2dx为我们提供了CCHttpRequest、CCHttpClient(单例)两个类来发起http请求,使用方法如下:
CCHttpRequest *pRequest = new CCHttpRequest();
pRequest->setUrl("http://127.0.0.1");
pRequest->setRequestType(CCHttpRequest::kHttpGet);
pRequest->setResponseCallback(this, callfuncND_selector(HttpSender::HttpCallBack)); //设置回调
CCHttpClient *pHttpClient = CCHttpClient::getInstance();
pHttpClient->send(pRequest);
这样发起一次连接还马马虎虎能够接受,但是一个应用程序会有很多不同的请求,如果每个请求都按照上述方法进行,将会很繁琐,
代码将会很难维护。有必要对http请求进行再一次的封装。
三,对http请求进行封装
需求:简化发起http请求的代码量,使代码易维护;
设计:一个类(HttpSender)负责发起http请求、接收回调消息,将得到的消息传递给使用者(HttpCallbackTarget);
类图如下:
四,类HttpCallbackTarget的实现如下
/
// CallbackTarget.h
// MyClient_CPP
//
// Created by Woodlouse on 14-9-3.
//
//
#ifndef __MyClient_CPP__HttpCallbackTarget__
#define __MyClient_CPP__HttpCallbackTarget__
//#include "CCObject.h"
#include "cocos2d.h"
namespace MyClient_CPP {
class HttpCallbackTarget {
public:
//NVI
void Callback(cocos2d::CCNode *pSrc, void *pData){
GetData(pSrc, pData);
}
protected:
HttpCallbackTarget(){};
virtual ~HttpCallbackTarget(){};
virtual void GetData(cocos2d::CCNode *pSrc, void *pData) = 0;
};
}
#endif /* defined(__MyClient_CPP__CallbackTarget__) */
五,HttpSender类的实现如下
//
// HttpSender.h
// MyClient_CPP
//
// Created on 14-9-3.
//
// Functon : 发送http请求
// Author : Woodlouse
#ifndef __MyClient_CPP__HttpSender__
#define __MyClient_CPP__HttpSender__
#include "HttpRequest.h"
using namespace cocos2d;
using namespace cocos2d::extension;
namespace MyClient_CPP{
class HttpCallbackTarget;
class HttpSender;
class HttpSender : public CCObject{
public:
HttpSender(HttpCallbackTarget *pAgent);
~HttpSender(){
CC_SAFE_RELEASE(m_pRequest);
}
public:
//初始化信息
void initRequest(const char *pUrl, CCHttpRequest::HttpRequestType type);
void initRequest(const char *pUrl, CCHttpRequest::HttpRequestType type, const char *pData, int len);
void send();
private:
CCHttpRequest* initRequest();
//接收http回应得回调
void HttpCallBack(CCNode *pRc, void *pData);
private:
CCHttpRequest *m_pRequest;
//代理
HttpCallbackTarget *m_pAgent;
};
}
#endif /* defined(__MyClient_CPP__HttpSender__) */
.cpp如下:
//
// HttpSender.cpp
// MyClient_CPP
//
// Created by Woodlouse on 14-9-3.
//
//
#include "HttpSender.h"
#include "HttpCallbackTarget.h"
#include "HttpClient.h"
using namespace MyClient_CPP;
HttpSender::HttpSender(HttpCallbackTarget *pAgent):
m_pRequest(NULL),
m_pAgent(NULL)
{
if(!pAgent) {
CCAssert(false, "Got an bad Agent");
return;
}
m_pAgent = pAgent;
}
CCHttpRequest* HttpSender::initRequest()
{
if (m_pRequest) {
return m_pRequest;
}
m_pRequest = new CCHttpRequest();
if (!m_pRequest) {
return NULL;
}
//设置回调
m_pRequest->setResponseCallback(this, callfuncND_selector(HttpSender::HttpCallBack));
return m_pRequest;
}
void HttpSender::initRequest(const char *pUrl, CCHttpRequest::HttpRequestType type)
{
if (!pUrl) {
CCAssert(false, "Got an bad url !!");
return;
}
if (!initRequest()) {
//初始化失败
CCLOG("Init HttpSender Error!!");
return;
}
m_pRequest->setUrl(pUrl);
m_pRequest->setRequestType(type);
}
void HttpSender::initRequest(const char *pUrl, CCHttpRequest::HttpRequestType type, const char *pData, int len)
{
if (!pData || len<=0) {
CCAssert(false, "Got an bad data");
return;
}
this->initRequest(pUrl, type);
m_pRequest->setRequestData(pData, len);
}
void HttpSender::HttpCallBack(CCNode *pRc, void *pData)
{
if (!m_pAgent) {
return;
}
m_pAgent->Callback(pRc, pData);
}
void HttpSender::send()
{
CCHttpClient *pHttpClient = CCHttpClient::getInstance();
pHttpClient->send(m_pRequest);
}
六,修改HelloWorldScene.h
对类ClassWorld添加继承类HttpCallbackTarget :
class HelloWorld : public cocos2d::CCLayer, public HttpCallbackTarget
添加函数定义:
void GetData(CCNode *pNode, void *pData);
void SendRequest(CCObject*, CCControlEvent);
添加成员变量:
HttpSender *m_pHttpSender;
七,在HelloWorldScene.cpp中添加测试代码
在init()函数中添加一个测试按钮“Send Requrest”:
CCControlButton* pButton = CCControlButton::create("Send request", "Thonburi", 34);
this->addChild(pButton, 1);
pButton->setPosition(ccp(size.width/2, 35));
pButton->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::SendRequest), CCControlEventTouchDown);
实现发送函数:
void HelloWorld::SendRequest(CCObject* prc, CCControlEvent evt)
{
if (!m_pHttpSender) {
m_pHttpSender = new HttpSender(this);
}
m_pHttpSender->initRequest("http://127.0.0.1:8888", CCHttpRequest::kHttpGet);//连接我们自己的服务器
m_pHttpSender->send();
CCLOG("Send request !!!");
}
实现收到数据的回调函数:
void HelloWorld::GetData(CCNode *pNode, void *pData)
{
if (!pData) {
return;
}
CCHttpResponse *pResponse = (CCHttpResponse*)pData;
if(pResponse->getResponseCode() != 200){
//错误
CCLOG("Error code is %d, and reason is %s ***", pResponse->getResponseCode(), pResponse->getErrorBuffer());
return;
}
//数据
std::vector<char>* pReceiveData = pResponse->getResponseData();
std::stringstream oss;
for (int i=0; i<pReceiveData->size(); ++i) {
oss<<(*pReceiveData)[i];
}
std::string temp = oss.str();
const char* buf = temp.c_str();
CCLOG("Receive msg is = %s *** ", buf);
}
在此,我们只把我们收到的数据打印出来。
八,总结
这种对http服务进行了最简单的封装,没有设定超时的处理;每一个场景同时只能发送一个http请求。
源码:http://download.csdn.net/detail/thekingofc/7949617