Cocos2dX通过Java服务器向Unity传输数据二

下面介绍Cocos2dX的相关代码,这里挺郁闷的。开始的TCP协议是基于Linux的,也就是说只能用Eclipse软件编辑,本身能用,但是它调试太慢了,受不了,于是找到了c++的socket,于是把两者结合一起,调试时用VS,发布时用Eclipse,这样就爽了,但还有小问题,不过目前不用解决,就是如果发布IOS,还有加代码。我查了Cocos的官方文件,他们用的是socket.IO,这个很好,但是没时间研究了,以后开发IOS时,再深入研究吧。

废话不说,代码如下:

/*
 * SocketBase.h
 *
 *  Created on: 2016年3月8日
 *      Author: Administrator
 */

#ifndef SOCKETBASE_H_
#define SOCKETBASE_H_

#include "cocos2d.h"
#include <list>
#include <thread>
USING_NS_CC;

#if(CC_TARGET_PLATFORM==CC_PLATFORM_WIN32)
#include <WinSock2.h>
#pragma comment(lib,"WS2_32.lib")
#define HSocket SOCKET

#elif(CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID)
//#include <error.h>
#include <arpa/inet.h>		// for inet_**
#include <netdb.h>			// for gethost**
#include <netinet/in.h>		// for sockaddr_in
#include <sys/types.h>		// for socket
#include <sys/socket.h>		// for socket
#include <unistd.h>
#include <stdio.h>		    // for printf
#include <stdlib.h>			// for exit
#include <string.h>			// for bzero
#define HSocket int
#endif

enum MessageType
{
	disCONNECT,RECEIVE,NEW_CONNECTION
};

class SocketMessage
{
private:
	MessageType msgType;
	Data* msgData;

public:
	SocketMessage(MessageType type,unsigned char* data,int dataLen)
	{
		msgType = type;
		msgData = new Data();
		msgData->copy(data,dataLen);
	}

	SocketMessage(MessageType type){
		msgType = type;
		msgData = nullptr;
	}

	Data* getMsgData(){ return msgData; }
	MessageType getMsgType(){ return msgType; }

	~SocketMessage()
	{
		if (msgData)CC_SAFE_DELETE(msgData);
	}

};

class SocketBase:public Ref
{
public:
	SocketBase();
	~SocketBase();

	bool nonBlock(HSocket socket);

protected:
	void closeConnect(HSocket socket);
	bool error(HSocket socket);

protected:
	std::mutex _mutex;

private:
	bool _bInitSuccess;

};


#endif /* SOCKETBASE_H_ */

/*
 * SocketBase.cpp
 *
 *  Created on: 2016年3月8日
 *      Author: Administrator
 */
#include "SocketBase.h"

SocketBase::SocketBase()
{
	_bInitSuccess = false;

#if(CC_TARGET_PLATFORM==CC_PLATFORM_WIN32)
	WORD wVersionRequested;
	wVersionRequested = MAKEWORD(2,0);
	WSADATA wsaData;
	int nRet = WSAStartup(wVersionRequested,&wsaData);
	if (nRet != 0)
	{
		fprintf(stderr,"Initilize Error!\n");
		return;
	}
	_bInitSuccess = true;
#endif
	
}

SocketBase::~SocketBase()
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
	if (_bInitSuccess)
	{
		WSACleanup();
	}
#endif 
}

void SocketBase::closeConnect(HSocket socket)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
	close(socket);
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
	closesocket(socket);
#endif
}

bool SocketBase::error(HSocket socket)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
	return socket == SOCKET_ERROR;
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
	return socket < 0;
#endif
}

bool SocketBase::nonBlock(HSocket socket)
{
//#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
//
//	int flags;
//	flags = fcntl(socket,F_GETFL,0);
//	flags != O_NONBLOCK;
//	if (fcntl(socket,F_SETFL,flags) < 0)
//	{
//		return false;
//	}
//#else
//	u_long ulOn;
//	ulOn = 1;
//	if (ioctlsocket(socket,FIONBIO,&ulOn) == SOCKET_ERROR)
//	{
//		return false;
//	}
//#endif

	return true;
}


/*
 * SocketClient.h
 *
 *  Created on: 2016年3月8日
 *      Author: Administrator
 */

#ifndef SOCKETCLIENT_H_
#define SOCKETCLIENT_H_
#include "SocketBase.h"

class SocketClient :public SocketBase
{
public:
	static SocketClient* construct();
	void destroy();

	bool connectServer(const char* serverIP,unsigned short port);
	void sendMessage(const char* data,int count);
	void sendInt(int num);

	std::function<void(const char* data,int count)> onRecv;
	std::function<void()> ondisconnect;

	void update(float dt);

CC_CONSTRUCTOR_ACCESS:
	SocketClient(void);
	~SocketClient(void);

private:
	bool initClient();
	void recvMessage();
	void clear();

private:
	HSocket _socketServer;
	HSocket _socektClient;
	std::list<SocketMessage*> _UIMessageQueue;
	std::mutex   _UIMessageQueueMutex;
};



#endif /* SOCKETCLIENT_H_ */

/*
 * SocketClient.cpp
 *
 *  Created on: 2016年3月8日
 *      Author: Administrator
 */
#include "SocketClient.h"

SocketClient* SocketClient::construct()
{
	SocketClient* client = new SocketClient;
	return client;
}

void SocketClient::destroy()
{
	delete this;
}

SocketClient::SocketClient(void) :
onRecv(nullptr),_socektClient(0)
{
}

SocketClient::~SocketClient(void)
{
	this->clear();
}

void SocketClient::clear()
{
	if (_socektClient != 0)
	{
		_mutex.lock();
		this->closeConnect(_socektClient);
		_mutex.unlock();
	}

	for (auto msg : _UIMessageQueue)
	{
		CC_SAFE_DELETE(msg);
	}
	_UIMessageQueue.clear();

	Director::getInstance()->getScheduler()->unscheduleAllForTarget(this);
}

bool SocketClient::initClient()
{
	this->clear();

	_socektClient = socket(AF_INET,SOCK_STREAM,0);
	if (error(_socketServer))
	{
		log("init client error!");
		_socektClient = 0;
		return false;
	}

	Director::getInstance()->getScheduler()->scheduleUpdate(this,false);
	return true;
}

bool SocketClient::connectServer(const char* serverIP,unsigned short port)
{
	if (!this->initClient())
	{
		return false;
	}

	struct sockaddr_in serverAddr;
	memset(&serverAddr,sizeof(struct sockaddr_in));

	serverAddr.sin_family = AF_INET;
	serverAddr.sin_port = htons(port);
	serverAddr.sin_addr.s_addr = inet_addr(serverIP);

	int ret = 0;
	ret = connect(_socektClient,(struct sockaddr*)&serverAddr,sizeof(struct sockaddr));
	if (ret < 0)
	{
		_socektClient = 0;
		return false;
	}

	std::thread recvThread(&SocketClient::recvMessage,this);
	recvThread.detach();

	return true;
}

void SocketClient::recvMessage()
{
	char recvBuf[1024];
	int ret = 0;
	while (true)
	{
		ret = recv(_socektClient,recvBuf,sizeof(recvBuf),0);
		if (ret < 0)
		{
			log("recv error!");
			break;
		}
		if (ret > 0 && onRecv != nullptr)
		{
			std::lock_guard<std::mutex> lk(_UIMessageQueueMutex);
			SocketMessage * msg = new SocketMessage(RECEIVE,(unsigned char*)recvBuf,ret);
			_UIMessageQueue.push_back(msg);
		}
	}
	_mutex.lock();
	this->closeConnect(_socektClient);
	if (ondisconnect != nullptr)
	{
		std::lock_guard<std::mutex> lk(_UIMessageQueueMutex);
		SocketMessage * msg = new SocketMessage(disCONNECT);
		_UIMessageQueue.push_back(msg);
	}
	_socektClient = 0;
	_mutex.unlock();
}

void SocketClient::sendMessage(const char* data,int count)
{
	sendInt(count);
	if (_socektClient != 0)
	{
		int ret = send(_socektClient,data,count,0);
		if (ret < 0)
		{
			log("send error!");
		}
	}
}

void SocketClient::sendInt(int num){
	if (_socektClient != 0){
		char ch[4];
		memcpy(ch,&num,4);
		int ret = send(_socektClient,ch,4,0);
		if (ret < 0){
			log("send error!");
		}
	}
}

void SocketClient::update(float dt)
{
	if (_UIMessageQueue.size() == 0)
	{
		return;
	}

	_UIMessageQueueMutex.lock();

	if (_UIMessageQueue.size() == 0)
	{
		_UIMessageQueueMutex.unlock();
		return;
	}

	SocketMessage *msg = *(_UIMessageQueue.begin());
	_UIMessageQueue.pop_front();

	switch (msg->getMsgType())
	{
	case disCONNECT:
		if (ondisconnect)
		{
			this->ondisconnect();
		}
		break;
	case RECEIVE:
		if (onRecv)
		{
			this->onRecv((const char*)msg->getMsgData()->getBytes(),msg->getMsgData()->getSize());
		}
		break;
	default:
		break;
	}

	CC_SAFE_DELETE(msg);
	_UIMessageQueueMutex.unlock();
}


#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

using namespace cocos2d::ui;
#include "cocostudio/CocoStudio.h"
#include "ui/CocosGUI.h"

class HelloWorld : public cocos2d::Layer
{
public:
	Text* text;
	Slider* slider;

	CREATE_FUNC(HelloWorld);

    static cocos2d::Scene* createScene();

    virtual bool init();
	void touchEvent(cocos2d::Ref *pSender,Widget::TouchEventType type);
	void sliderEvent(cocos2d::Ref* sender,Slider::EventType type);
};

#endif // __HELLOWORLD_SCENE_H__

#include "HelloWorldScene.h"
#include "Network/UtilTcp.h"
#include "Network\SocketClient.h"
//#include "Network/UtilTcp1.h"

USING_NS_CC;
using namespace ui;
using namespace cocostudio;
using namespace cocostudio::timeline;
SocketClient* client;
Scene* HelloWorld::createScene() {
	auto scene = Scene::create();

	auto layer = HelloWorld::create();

	scene->addChild(layer);

	return scene;
}

bool HelloWorld::init() {
	if (!Layer::init()) {
		return false;
	}
	auto rootNode = csloader::createNode("MainScene.csb");
	Button* closeBt = static_cast<Button*>(rootNode->getChildByTag(304));
	closeBt->addTouchEventListener(CC_CALLBACK_2(HelloWorld::touchEvent,this));
	slider = static_cast<Slider*>(rootNode->getChildByTag(301));
	slider->setMaxPercent(100);
	slider->addEventListener(CC_CALLBACK_2(HelloWorld::sliderEvent,this));
	text = static_cast<Text*>(rootNode->getChildByTag(302));
	addChild(rootNode);
	//new std::thread(&UtilTcp::threadConnectServer,"172.27.35.1",59422);
	//new std::thread(&UtilTcp1::threadConnectTask,59422);
	 client = SocketClient().construct();
	 client->connectServer("172.27.35.1",59422);
	return true;
}

void HelloWorld::sliderEvent(Ref *pSender,Slider::EventType type) {
	if (type == Slider::EventType::ON_PERCENTAGE_CHANGED) {
		text->setText(StringUtils::format("%d",slider->getPercent()));
		client->sendMessage("COCOS",5);
		client->sendInt(slider->getPercent());
//		if (slider->getPercent() <= 9) {
//			UtilTcp::sendMessage(std::string(text->getString()).c_str(),1);
//			UtilTcp::sendInt(slider->getPercent());
////			client->sendMessage(std::string(text->getString()).c_str(),1);
//
//			UtilTcp1::sendStr("COCOS",5);
//			UtilTcp1::sendInt(slider->getPercent());
//		}
//		if (slider->getPercent() > 10 && slider->getPercent() < 100) {
//			//UtilTcp::sendInt(2);
//			//UtilTcp::sendMessage(std::string(text->getString()).c_str(),2);
//			//client->sendInt(2);
////			client->sendMessage(std::string(text->getString()).c_str(),2);
//			UtilTcp1::sendStr("COCOS",5);
//			UtilTcp1::sendInt(slider->getPercent());
//		}
//		if (slider->getPercent() == 100) {
//			/*UtilTcp::sendInt(3);
//			UtilTcp::sendMessage(std::string(text->getString()).c_str(),3);*/
////			client->sendMessage(std::string(text->getString()).c_str(),3);
//			UtilTcp1::sendStr("COCOS",5);
//			UtilTcp1::sendInt(slider->getPercent());
//		}

	}
}

void HelloWorld::touchEvent(Ref *pSender,Widget::TouchEventType type) {
	switch (type) {
	case Widget::TouchEventType::BEGAN: {
		Director::getInstance()->end();
#if (CC_TARGET_PLATFORM==CC_PLATFORM_IOS)
		exit(0);
#endif
	}
		break;
	default:
		break;
	}
}

相关文章

    本文实践自 RayWenderlich、Ali Hafizji 的文章《...
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@1...
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从C...
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发...
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《...
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试...