在使用CCHttpClient前首先需要搭建一个Apache服务器
搭建Apache服务器和使用Apache服务器的方法可以参考下面的博客:
在Windows下搭建Apache服务器:http://blog.csdn.net/u010105970/article/details/41276451
开发基于Apache服务器上的CGI程序:http://blog.csdn.net/u010105970/article/details/41278489
一步一步教你使用CGI实现一个简单的后门:http://blog.csdn.net/u010105970/article/details/41345967
程序实例1:在Cocos2d-X中使用CCHttpClient实现登陆验证
使用VS2012编译下面的代码(服务器端的代码):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
//设置HTML语言
printf("Content-type:text/html\n\n");
//通过环境变量得到用户传递的参数
char* queryString = getenv("QUERY_STRING");
//分解字符串queryString
//将字符串queryString分割成两个字符串,'|'为分隔符
char* username = strtok(queryString, "|");
char* password = strtok(NULL, "|");
//判断用户名和密码是否输入正确
if(0 == strcmp(username, "aaa") && 0 == strcmp(password, "bbb"))
{
printf("Login success !<br>");
}
else
{
printf("Login Error !<br>");
}
}
编译成功后将程序复制到Apache服务器中
在浏览器中输入:http://localhost/cgi-bin/login.cgi?aaa|bbb
在浏览器中输入:http://localhost/cgi-bin/login.cgi?aaaa
通过上面的例子证明服务器端的程序编译成功,并且程序实现了一个简单的验证,当用户传递的参数是aaa|bbb时验证成功,当用户传递的参数不是aaa|bbb时验证失败
客服端的代码
当Cocos2d-X作为客服端执行这个程序时,首先创建一个HttpClient类,在HttpClient.h中添加下面的代码
#ifndef __HttpClient_H__
#define __HttpClient_H__
#include "cocos2d.h"
#include "cocos-ext.h"
using namespace cocos2d::extension;
USING_NS_CC;
class HttpClient : public CCLayer
{
public:
static CCScene* scene();
CREATE_FUNC(HttpClient);
bool init();
void httpResponse(CCHttpClient* client, CCHttpResponse* response);
};
#endif
在HttpClient.cpp中添加下面的代码
#include "HttpClient.h"
CCScene* HttpClient::scene()
{
CCScene* s = CCScene::create();
HttpClient* layer = HttpClient::create();
s->addChild(layer);
return s;
}
bool HttpClient::init()
{
CCLayer::init();
//获得网络共享实例
CCHttpClient* httpClient = CCHttpClient::getInstance();
//创建一个请求
CCHttpRequest* request = new CCHttpRequest;
//设置请求访问的地址
request->setUrl("http://localhost/cgi-bin/login.cgi?aaa|bbb");
//设置响应回调函数,读取response
request->setResponseCallback(this, httpresponse_selector(HttpClient::httpResponse));
//设置请求的类型 (GET、POST等)
request->setRequestType(CCHttpRequest::kHttpGet);
//发送请求
httpClient->send(request);
//释放请求
request->release();
return true;
}
//定义HttpClient的响应函数
void HttpClient::httpResponse(CCHttpClient* client, CCHttpResponse* response)
{
//如果访问服务器失败
if (!response->isSucceed())
{
//定义一个指针保存错误信息
const char* err = response->getErrorBuffer();
//打印错误信息
CCLog("response error = %s", err);
return;
}
//创建一个向量保存服务器中传过来的数据
std::vector<char>* vChar = response->getResponseData();
std::string str;
std::vector<char>::iterator it;
for (it = vChar->begin(); it != vChar->end(); it++)
{
str += *it;
}
//打印服务器传到客服端的数据
CCLog("%s", str.c_str());
}
执行结果:
将HttpClient.cpp下的HttpClient::init()中的
//设置请求访问的地址
request->setUrl(<a target=_blank href="http://localhost/cgi-bin/login.cgi?aaa|bbb">http://localhost/cgi-bin/login.cgi?aaa|bbb</a>);
改成
//设置请求访问的地址
request->setUrl(<a target=_blank href="http://localhost/cgi-bin/login.cgi?aaa|bbb">http://localhost/cgi-bin/login.cgi?aaa|bbb</a>);
后的执行结果:
程序实例2:在Cocos2d-X中使用CCHttpClient实现客服端向服务器发送数据服务器处理客服端的数据并且返回数据
使用VS2012编译下面的代码(服务器端的代码):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
//设置HTML语言
printf("Content-type:text/html\n\n");
//得到上传的数据的长度
char* contentLength = getenv("CONTENT_LENGTH");
//将字符串转换成型
int length = atoi(contentLength);
//打印数据的长度
printf("content length = %d<br>\n", length);
//动态内存分配
char* buf = (char*)malloc(length);
//将buf清零
memset(buf, 0, length);
//将stdin(缓冲区)中的数据读取到buf中
fread(buf, length, 1, stdin);
//打印buf中的数据
printf("%s<br>\n", buf);
//释放内存
free(buf);
}
客服端代码:
#include "HttpClient.h"
CCScene* HttpClient::scene()
{
CCScene* s = CCScene::create();
HttpClient* layer = HttpClient::create();
s->addChild(layer);
return s;
}
bool HttpClient::init()
{
CCLayer::init();
//获得网络共享实例
CCHttpClient* httpClient = CCHttpClient::getInstance();
//创建一个请求
CCHttpRequest* request = new CCHttpRequest;
//设置请求的类型为POST
request->setRequestType(CCHttpRequest::kHttpPost);
//设置请求访问的地址
request->setUrl("http://localhost/cgi-bin/login1.cgi");
//设置回调函数
request->setResponseCallback(this, httpresponse_selector(HttpClient::httpResponse));
//设置向服务器发送的数据
request->setRequestData("aaa|bbb|", 8);
//连接超时
httpClient->setTimeoutForConnect(30);
//发送请求
httpClient->send(request);
//释放请求
request->release();
return true;
}
//定义HttpClient的响应函数
void HttpClient::httpResponse(CCHttpClient* client, CCHttpResponse* response)
{
//如果访问服务器失败
if (!response->isSucceed())
{
//定义一个指针保存错误信息
const char* err = response->getErrorBuffer();
//打印错误信息
CCLog("response error = %s", err);
return;
}
//创建一个向量保存服务器中传过来的数据
std::vector<char>* vChar = response->getResponseData();
std::string str;
std::vector<char>::iterator it;
for (it = vChar->begin(); it != vChar->end(); it++)
{
str += *it;
}
//打印服务器传到客服端的数据
CCLog("%s", str.c_str());
}
执行结果:
程序实例3:在Cocos2d-X中使用CCHttpClient实现一个简单的登录功能
服务器端代码:
使用VS2012编译下面的代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
//设置HTML语言
printf("Content-type:text/html\n\n");
//得到上传的数据的长度
char* contentLength = getenv("CONTENT_LENGTH");
//将字符串转换成型
int length = atoi(contentLength);
//动态内存分配
char* buf = (char*)malloc(length);
//将buf清零
memset(buf, 0, length);
//将stdin(缓冲区)中的数据读取到buf中
fread(buf, length, 1, stdin);
//分解字符串queryString
//将字符串queryString分割成两个字符串,'|'为分隔符
char* username = strtok(buf, "|");
char* password = strtok(NULL, "|");
//判断用户名和密码是否输入正确
//用户名和密码都输入正确
if(0 == strcmp(username, "aaa") && 0 == strcmp(password, "bbb"))
{
printf("0");
}
//用户名输入错误密码输入正确
else if(0 != strcmp(username, "aaa") && 0 == strcmp(password, "bbb"))
{
printf("1");
}
//用户名输入正确密码输入错误
else if(0 == strcmp(username, "aaa") && 0 != strcmp(password, "bbb"))
{
printf("2");
}
//用户名和密码都输入错误
else
{
printf("3");
}
//释放内存
free(buf);
}
服务器端实现的功能:
1、设置正确的用户名为aaa,正确的密码为bbb
2、获得用户从客户端端发到服务器的用户名和密码
3、判断用户名和密码是否正确
4、当用户名和密码都正确时,发送0到客户端
5、当用户名错误,密码正确时,发送1到客户端
6、当用户名正确,密码错误时,发送2到客户端
7、当用户名错误,密码也错误时,发送3到客户端
将上面的代码编译成的exe文件拷贝到C:\Program Files\Apache Software Foundation\Apache2.2\cgi-bin中,并且将exe从命名为login.cgi
使用Cocos2d-X实现登陆功能的客户端:
首先创建一个xml格式的plist文件用于处理中文,因为在Cocos2d-X中直接使用中文会出现乱码,创建一个information.plist格式的xml文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>username</key>
<string>用户名</string>
<key>password</key>
<string>密码</string>
<key>isusername</key>
<string>用户名错误</string>
<key>ispassword</key>
<string>密码错误</string>
<key>login</key>
<string>登录成功</string>
</dict>
</plist>
创建一个Login类,在Login.h中添加下面的代码
#ifndef _Login_H_
#define _Login_H_
#include "cocos2d.h"
#include "cocos-ext.h"
using namespace cocos2d::extension;
USING_NS_CC;
class Login : public CCLayer
{
public:
static CCScene* scene();
bool init();
CREATE_FUNC(Login);
//菜单响应函数
void menuHandler(CCObject*);
//定义HttpClient的响应函数
void httpResponse(CCHttpClient* client, CCHttpResponse* response);
CCLabelTTF* label3;
CCLabelTTF* label4;
CCLabelTTF* label5;
char strName[256];
char strPassword[256];
CCEditBox* m_pEditName;
CCEditBox* m_pEditPassword;
};
#endif
在Login.cpp中添加下面的代码
#include "Login.h"
CCScene* Login::scene()
{
static CCScene* scene = CCScene::create();
Login* layer = Login::create();
scene->addChild(layer);
return scene;
}
bool Login::init()
{
CCLayer::init();
//得到窗口的大小
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
char UserName[256];//保存用户名
char Password[256];//保存密码
char isUserName[256];//保存用户名的判断结果
char isPassword[256];//保存密码的判断结果
char Login[256];//保存登录结果
//创建一个字典类,用于读取plist格式的xml文件
CCDictionary* dict = CCDictionary::createWithContentsOfFile("information.plist");
//从infmation.plist中读取用户名
const CCString* username = dict->valueForKey("username");
sprintf(UserName, "%s", username->getCString());
//从information.plist中读取密码
const CCString* password = dict->valueForKey("password");
sprintf(Password, "%s", password->getCString());
//从information.plist中读取用户名的判断结果
const CCString* isusername = dict->valueForKey("isusername");
sprintf(isUserName, "%s", isusername->getCString());
//从information.plist中读取密码的判断结果
const CCString* ispassword = dict->valueForKey("ispassword");
sprintf(isPassword, "%s", ispassword->getCString());
//从information.plist中读取登录的结果
const CCString* login = dict->valueForKey("login");
sprintf(Login, "%s", login->getCString());
CCLabelTTF* label1 = CCLabelTTF::create(UserName, "Arial", 25);
CCLabelTTF* label2 = CCLabelTTF::create(Password, "Arial", 25);
label3 = CCLabelTTF::create(isUserName, "Arial", 25);
label4 = CCLabelTTF::create(isPassword, "Arial", 25);
label5 = CCLabelTTF::create(Login, "Arial", 25);
addChild(label1);
addChild(label2);
addChild(label3);
addChild(label4);
addChild(label5);
label1->setPosition(ccp(winSize.width / 2 - 100, winSize.height / 2 + 100));
label2->setPosition(ccp(winSize.width / 2 - 100, winSize.height / 2 + 60));
label3->setPosition(ccp(winSize.width / 2, winSize.height / 2 - 50));
label4->setPosition(ccp(winSize.width / 2, winSize.height / 2 - 80));
label5->setPosition(ccp(winSize.width / 2, winSize.height / 2 - 50));
label3->setVisible(false);
label4->setVisible(false);
label5->setVisible(false);
//创建CCEditBox控件用于输入用户名
m_pEditName = CCEditBox::create(CCSizeMake(winSize.width / 3, 30), CCScale9Sprite::create("green_edit.png"));
//设置CCEditBox控件的位置
m_pEditName->setPosition(ccp(winSize.width - 220, winSize.height / 2 + 100));
//添加CCEditBox控件
addChild(m_pEditName);
//设置CCEditBox中文本的大小
m_pEditName->setFontSize(10);
//设置CCEditBox中文本的颜色
m_pEditName->setFontColor(ccBLACK);
//设置CCEditBox为空时,CCEditBox控件的颜色
m_pEditName->setPlaceholderFontColor(ccBLACK);
//设置最多可以输入的字符数
m_pEditName->setMaxLength(8);
//设置软键盘中回车按钮的样子
m_pEditName->setReturnType(kKeyboardReturnTypeGo);
//设置输入模式
//kEditBoxInputModeAny表示可以输入任何数据
m_pEditName->setInputMode(kEditBoxInputModeAny);
//创建CCEditBox控件
m_pEditPassword = CCEditBox::create(CCSizeMake(winSize.width / 3, 30), CCScale9Sprite::create("yellow_edit.png"));
//设置CCEditBox控件的位置
m_pEditPassword->setPosition(ccp(winSize.width - 220, winSize.height / 2 + 60));
//添加CCEditBox控件
addChild(m_pEditPassword);
//设置CCEditBox中文本的颜色
m_pEditPassword->setFontColor(ccBLACK);
//设置CCEditBox控件中最多显示的字符的个数
m_pEditPassword->setMaxLength(10);
//设置输入的属性
//kEditBoxInputFlagPassword:输入的是密码
m_pEditPassword->setInputFlag(kEditBoxInputFlagPassword);
//设置输入编辑框的编辑类型
//kEditBoxInputModeSingleLine: 开启任何文本的输入键盘,不包括换行
m_pEditPassword->setInputMode(kEditBoxInputModeSingleLine);
//创建菜单
CCMenu* menu = CCMenu::create();
addChild(menu);
//创建菜单项
CCMenuItemImage* LoginMenu = CCMenuItemImage::create("button.png", "button.png");
menu->addChild(LoginMenu);
//设置菜单响应函数
LoginMenu->setTarget(this, menu_selector(Login::menuHandler));
return true;
}
//菜单响应函数
void Login::menuHandler(CCObject*)
{
sprintf(strName, "%s", m_pEditName->getText());
sprintf(strPassword, "%s", m_pEditPassword->getText());
//保存向服务器发送的数据
char strSend[256];
sprintf(strSend, "%s|%s", strName, strPassword);
//获得网络共享实例
CCHttpClient* httpClient = CCHttpClient::getInstance();
//创建一个请求
CCHttpRequest* request = new CCHttpRequest;
//设置请求的类型为POST
request->setRequestType(CCHttpRequest::kHttpPost);
//设置请求访问的地址
request->setUrl("http://localhost/cgi-bin/login.cgi");
//设置回调函数
request->setResponseCallback(this, httpresponse_selector(Login::httpResponse));
//设置向服务器发送的数据
request->setRequestData(strSend, sizeof(strSend));
//连接超时
httpClient->setTimeoutForConnect(30);
//发送请求
httpClient->send(request);
//释放请求
request->release();
}
//定义HttpClient的响应函数
void Login::httpResponse(CCHttpClient* client, CCHttpResponse* response)
{
//如果访问服务器失败
if (!response->isSucceed())
{
//定义一个指针保存错误信息
const char* err = response->getErrorBuffer();
//打印错误信息
CCLog("response error = %s", err);
return;
}
//创建一个向量保存服务器中传过来的数据
std::vector<char>* vChar = response->getResponseData();
std::string str;
std::vector<char>::iterator it;
for (it = vChar->begin(); it != vChar->end(); it++)
{
str += *it;
}
//打印服务器传到客服端的数据
CCLog("%s", str.c_str());
//将服务器传到客服端的数据转换成整型
int num = atoi(str.c_str());
switch(num)
{
case 0://登录成功
label5->setVisible(true);
break;
case 1://用户名错误
label3->setVisible(true);
break;
case 2://密码错误
label4->setVisible(true);
break;
case 3://用户名和密码都错误
label3->setVisible(true);
label4->setVisible(true);
break;
default:
break;
}
}
客服端实现的功能:
1、输入用户名和密码
2、将用户名和密码发送给服务器
3、接收服务器发送到客服端的数据
4、当接收的数据为0时,表示用户名和密码输入正确,在界面上显示”登录成功“
5、当接收的数据为1时,表示用户名错误,密码正确,在界面上显示”用户名错误“
6、当接收的数据为2时,表示用户名正确,密码错误,在界面上显示"密码错误"
4、当接收的数据为3时,表示用户名和密码都错误,在界面上显示”用户名错误“、”密码错误“
执行结果:
当在用户名中输入aaa,密码中输入bbb,后单击登录会显示登录成功
当在用户名中输入a,密码中输入bbb,后单击登录会显示用户名错误
当在用户名中输入aaa,密码中输入b,后单击登录会显示密码错误
当在用户名中输入a,密码中输入b,后单击登录会显示用户名错误、密码错误