cocos2d-x3.2 Socket传输Json字符串
来源:互联网 发布:河北大学新区淘宝地址 编辑:程序博客网 时间:2024/05/16 18:58
这里使用客户端用的是C++的简单封装,参考http://blog.csdn.net/langresser_king/article/details/8646088这篇文章。
原文地址:http://blog.csdn.net/qqmcy/article/details/39155541
代码下载:http://download.csdn.net/detail/qqmcy/7884273
服务器端用的JAVA编写。测试服务器代码:http://download.csdn.net/detail/qqmcy/7884327 这个服务器代码只适合测试使用。
使用方法:
HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__#include "cocos2d.h"#include "Tools/SocketModel/DJAsyncSocket.h"class HelloWorld : public cocos2d::Layer ,public DJAsyncSocketDelegate{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(); // implement the "static create()" method manually CREATE_FUNC(HelloWorld); void menuCloseCallback(Ref* sender); private: DJAsyncSocket* socket_asy; virtual void update(float delta); virtual void onSocketDidReadData(DJAsyncSocket* sock ,char* data); };#endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.cpp
#include "HelloWorldScene.h"#include "Tools/JsonData/MakeJson.h"USING_NS_CC;#define IP "127.0.0.1";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 instancebool HelloWorld::init(){ ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } socket_asy = new DJAsyncSocket(); socket_asy->setDelegate(this); socket_asy->create("127.0.0.1", 8000); auto visibleSize = Director::getInstance()->getVisibleSize(); auto origin = Director::getInstance()->getVisibleOrigin(); auto closeItem = MenuItemImage::create( "choose_btn_light.png", "choose_btn_light.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback,this)); closeItem->setPosition(origin + Vec2(visibleSize) - Vec2(closeItem->getContentSize() / 2)); // create menu, it's an autorelease object auto menu = Menu::create(closeItem, NULL); menu->setPosition(Vec2::ZERO); this->addChild(menu, 1); this->scheduleUpdate(); return true;}void HelloWorld::menuCloseCallback(Ref* sender){ MakeJson* mjson = MakeJson::create(); std::string content = mjson->getTestJson(); content.append("\n"); // const char* str_cnt = content.c_str(); int len = (int)content.length(); //"{ \"hello\" : \"world\" }";// char* str = nullptr;//"{\"reciver\":\"555\",\"sender\":\"f\"}\n"; char* str = (char*)malloc((len)* sizeof(char)); content.copy(str, len,0); // log("content = %s,length = %lu ,Len = %d",content.c_str(),strlen(str),len); socket_asy->sendMsg(str, len); socket_asy->flush(); // free(str);// content = nullptr; }void HelloWorld::update(float delta){ // 接收消息处理(放到游戏主循环中,每帧处理) if (!socket_asy) { return; } // 接收数据(取得缓冲区中的所有消息,直到缓冲区为空) while (true) { char buffer[_MAX_MSGSIZE] = { 0 }; int nSize = sizeof(buffer); char* pbufMsg = buffer; if(socket_asy == NULL) { break; } if (!socket_asy->receiveMsg(pbufMsg, nSize)) { break; } } }void HelloWorld::onSocketDidReadData(DJAsyncSocket *sock, char *data){ log("data = %s",data); auto path = FileUtils::getInstance()->getWritablePath(); log("%s",path.c_str()); //在这个路径下添加一个json文件 path.append("test.json"); FILE* file = fopen(path.c_str(), "wb"); if (file) { fputs(data, file); fclose(file); }}
DJAsyncSocket.h
//// DJAsyncSocket.h// cpp4//// Created by 杜甲 on 14-9-5.////#ifndef __cpp4__DJAsyncSocket__#define __cpp4__DJAsyncSocket__#if WIN32#include <windows.h>#include <WinSock.h>#else#include <sys/socket.h>#include <fcntl.h>#include <errno.h>#include <netinet/in.h>#include <arpa/inet.h>#include <string.h>#include <sys/stat.h>#include <unistd.h>#define SOCKET int#define SOCKET_ERROR -1#define INVALID_SOCKET -1#endif#ifndef CHECHF#define CHECKF(x) \do \{ \if(!(x)) {\log("CHECK",#x,__FILE__,__LINE__);\return 0; \}\} while(0)#endif#define _MAX_MSGSIZE 8 * 1024 //暂定一个消息最大为16K#define BLOCKSECONDS 30 //INIT函数阻塞时间#define INBUFSIZE (64 * 1024) // 接收数据缓存#define OUTBUFSIZE (8 * 1024) // 发送数据的缓存,当不超过8K时,FLUSH只需要SEND一次#include "cocos2d.h"USING_NS_CC;class DJAsyncSocket;class DJAsyncSocketDelegate{public: virtual void onSocketDidReadData(DJAsyncSocket* sock ,char* data) = 0;};class DJAsyncSocket :public Ref{public: DJAsyncSocket(); bool create(const char* pszServerIP , int nServerPort , int nBlockSec = BLOCKSECONDS , bool bKeepAlice = false); bool sendMsg(void* pBuf , int nSize); bool receiveMsg(void* pBuf , int& nSize); bool flush(void); bool check(void); void destory(void); SOCKET getSocket(void) const ;private: CC_SYNTHESIZE(DJAsyncSocketDelegate*, _delegate, Delegate); bool recvFromSock(void); //从网络中读取尽可能多的数据 bool hasError(void); //是否发生错误,注意,异步模式未完成非错误 void closeSocket(void); SOCKET m_sockClient; //发送数据缓冲 char m_bufOutput[OUTBUFSIZE]; int m_nOutbufLen; //环形缓冲区 char m_bufInput[INBUFSIZE]; int m_nInbufLen; int m_nInbufStart; //INBUF使用循环式队列,该变量为队列起点,0 - (SIZE - 1)};#endif /* defined(__cpp4__DJAsyncSocket__) */
//// DJAsyncSocket.cpp// cpp4//// Created by 杜甲 on 14-9-5.////#include "DJAsyncSocket.h"DJAsyncSocket::DJAsyncSocket(){ //初始化 memset(m_bufOutput, 0, sizeof(m_bufOutput)); memset(m_bufInput, 0, sizeof(m_bufInput));}void DJAsyncSocket::closeSocket(){#ifdef WIN32 closeSocket(m_sockClient); WSACleanup();#else close(m_sockClient);#endif}bool DJAsyncSocket::create(const char *pszServerIP, int nServerPort, int nBlockSec, bool bKeepAlive /*= FALSE*/){ if (pszServerIP == 0 || strlen(pszServerIP) > 15) { return false; }#ifdef WIN32WSADATA wsaData;WORD version = MAKEWORD(2, 0);int ret = WSAStartup(version, &wsaData);//win sock start upif (ret != 0) {return false;}#endif // 创建主套接字 m_sockClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_sockClient == INVALID_SOCKET) { closeSocket(); return false; } //设置Socket为KEEPALIVE if (bKeepAlive) { int optval = 1; if (setsockopt(m_sockClient, SOL_SOCKET, SO_KEEPALIVE, (char*)& optval , sizeof(optval))) { closeSocket(); return false; } } #ifdef WIN32DWORD nMode = 1;int nRes = ioctlsocket(m_sockClient, FIONBIO, &nMode);if (nRes == SOCKET_ERROR) {closeSocket();return false;}#else// 设置为非阻塞方式fcntl(m_sockClient, F_SETFL, O_NONBLOCK);#endif unsigned long serveraddr = inet_addr(pszServerIP); if (serveraddr == INADDR_NONE) { //检查IP地址格式错误 closeSocket(); return false; } sockaddr_in addr_in; memset((void*)& addr_in, 0, sizeof(addr_in)); addr_in.sin_family = AF_INET; addr_in.sin_port = htons(nServerPort); addr_in.sin_addr.s_addr = serveraddr; if (connect(m_sockClient, (sockaddr*)& addr_in, sizeof(addr_in)) == SOCKET_ERROR) { if (hasError()) { closeSocket(); return false; } else // WSAWOLDBLOCK { timeval timeout; timeout.tv_sec = nBlockSec; timeout.tv_usec = 0; fd_set writeset,exceptset; FD_ZERO(&writeset); FD_ZERO(&exceptset); FD_SET(m_sockClient, &writeset); FD_SET(m_sockClient, &exceptset); int ret = select(FD_SETSIZE, NULL, &writeset, &exceptset, &timeout); if (ret == 0 || ret < 0) { closeSocket(); return false; }else //ret > 0 { ret = FD_ISSET(m_sockClient, &exceptset); if (ret) { closeSocket(); return false; } } } } m_nInbufLen = 0; m_nInbufStart = 0; m_nOutbufLen = 0; struct linger so_linger; so_linger.l_onoff = 1; so_linger.l_linger = 500; setsockopt(m_sockClient, SOL_SOCKET, SO_LINGER, (const char*)& so_linger, sizeof(so_linger)); return true;}bool DJAsyncSocket::hasError(){#ifdef WIN32int err = WSAGetLastError();if(err != WSAEWOULDBLOCK) { return true; } #else int err = errno; if(err != EINPROGRESS && err != EAGAIN) { return true; } #endif return false;}bool DJAsyncSocket::sendMsg(void *pBuf, int nSize){ if (pBuf == 0 || nSize <= 0) { return false; } if (m_sockClient == INVALID_SOCKET) { return false; } //检查通讯消息包长度 int packsize = 0; packsize = nSize; //检测BUF溢出 if (m_nOutbufLen + nSize > OUTBUFSIZE) { //立即发送OUTBUF中的数据,以清空OUTBUF flush(); if (m_nOutbufLen + nSize > OUTBUFSIZE) { destory(); return false; } } memcpy(m_bufOutput + m_nOutbufLen, pBuf, nSize); m_nOutbufLen += nSize; return true;}bool DJAsyncSocket::flush(){ if (m_sockClient == INVALID_SOCKET) { return false; } if (m_nOutbufLen <= 0) { return true; } //发送一段数据 int outsize; outsize = send(m_sockClient, m_bufOutput, m_nOutbufLen, 0); if (outsize > 0){ //删除已发送的部分 if (m_nOutbufLen - outsize > 0) { memcpy(m_bufOutput, m_bufOutput + outsize, m_nOutbufLen - outsize); } m_nOutbufLen -= outsize; if (m_nOutbufLen < 0) { return false; } }else{ if (hasError()) { destory(); return false; } } return true;}bool DJAsyncSocket::check(){ //检查状态 if (m_sockClient == INVALID_SOCKET) { return false; } char buf[1]; int ret = recv(m_sockClient, buf, 1, MSG_PEEK); if (ret == 0) { destory(); return false; }else if (ret < 0){ if (hasError()) { destory(); return false; }else{ return true; } }else{ return true; } return true;}bool DJAsyncSocket::receiveMsg(void *pBuf, int &nSize){ //检查参数 if (pBuf == NULL || nSize <= 0) { return false; } if (m_sockClient == INVALID_SOCKET) { return false; }// log("m_bufInput = %s,m_nInbufLen = %d",m_bufInput,m_nInbufLen); //检查是否有一个消息(小于2则无法获取到消息长度) if (m_nInbufLen < 2) { // 如果没有请求成功 或者 如果没有数据则直接返回 if (!recvFromSock() || m_nInbufLen < 2) { //这个m_nInbufLen更新了 return false; } } if (_delegate) { _delegate->onSocketDidReadData(this, m_bufInput); } //计算要拷贝的消息的大小(一个消息,大小为整个消息的第一个16字节),因为环形缓冲区,所以要分开结算 int packsize = (unsigned char) m_bufInput[m_nInbufStart] + (unsigned char)m_bufInput[(m_nInbufStart + 1) % INBUFSIZE] * 256; //注意字节序,高位 + 低位 //检测消息包尺寸错误 暂定最大16k if (packsize <= 0 || packsize > _MAX_MSGSIZE) { m_nInbufLen = 0; //直接清空INBUF m_nInbufStart = 0; return false; } //检查消息是否完整(如果将要拷贝的消息大于此时缓冲区数据长度,需要再次请求接收剩余数据) if (packsize > m_nInbufLen) { //如果没有请求成功 或者 依然无法获取到完整的数据包 则返回,直到取得wanzbao if (!recvFromSock() || packsize > m_nInbufLen) { //这个m_nInbufLen已更新 return false; } } // 复制出一个消息 if (m_nInbufStart + packsize > INBUFSIZE) { // 如果一个消息有回卷(被拆成两份在环形缓冲区的头尾) // 先拷贝环形缓冲区末尾的数据 int copylen = INBUFSIZE - m_nInbufStart; memcpy(pBuf, m_bufInput + m_nInbufStart, copylen); //再考贝环形缓冲区头部的剩余部分 memcpy((unsigned char*) pBuf + copylen, m_bufInput, packsize - copylen); nSize = packsize; }else { // 消息没有回卷,可以一次拷贝出去 memcpy(pBuf, m_bufInput + m_nInbufStart, packsize); nSize = packsize; }// log("m_bufInput = %s",m_bufInput); m_nInbufStart = (m_nInbufStart + packsize) % INBUFSIZE; m_nOutbufLen -= packsize; return true;}bool DJAsyncSocket::recvFromSock(){ if (m_nInbufLen >= INBUFSIZE || m_sockClient == INVALID_SOCKET) { return false; } //接收第一段数据 int savelen , savepos; //数据要保存的长度和位置 if (m_nInbufStart + m_nInbufLen < INBUFSIZE) { //INBUF中的剩余空间有回绕 savelen = INBUFSIZE - (m_nInbufStart + m_nInbufLen); //后部空间长度,最大接收数据的长度 }else{ savelen = INBUFSIZE - m_nInbufLen; } // 缓冲区数据的末尾 savepos = (m_nInbufStart + m_nInbufLen) % INBUFSIZE;// CHECKF(savepos + savelen < INBUFSIZE); int inlen = recv(m_sockClient, m_bufInput + savepos, savelen, 0); if (inlen > 0) { //有接收到数据 m_nInbufLen += inlen; if (m_nInbufLen > INBUFSIZE) { return false; } //接收第二段数据(一次接收没有完成,接收第二段数据) if (inlen == savelen && m_nInbufLen < INBUFSIZE) { int savelen = INBUFSIZE - m_nInbufLen; int savepos = (m_nInbufStart + m_nInbufLen) % INBUFSIZE;// CHECKF(savepos + savelen <= INBUFSIZE); inlen = recv(m_sockClient, m_bufInput + savepos, savelen, 0); if (inlen > 0) { m_nInbufLen += inlen; if (m_nInbufLen > INBUFSIZE) { return false; } }else if (inlen == 0){ destory(); return false; }else{ if (hasError()) { destory(); return false; } } } } return true;}void DJAsyncSocket::destory(){ // 关闭 struct linger so_linger; so_linger.l_onoff = 1; so_linger.l_linger = 500; int ret = setsockopt(m_sockClient, SOL_SOCKET, SO_LINGER, (const char*)& so_linger, sizeof(so_linger)); closeSocket(); m_sockClient = INVALID_SOCKET; m_nInbufLen = 0; m_nInbufStart = 0; m_nOutbufLen = 0; memset(m_bufOutput, 0, sizeof(m_bufOutput)); memset(m_bufInput, 0, sizeof(m_bufInput));}
下面是制作JSON数据的类
MakeJson.h
//// MakeJson.h// cpp4//// Created by 杜甲 on 14-9-9.////#ifndef __cpp4__MakeJson__#define __cpp4__MakeJson__#include "cocos2d.h"#include "json/document.h"#include "json/writer.h"#include "json/stringbuffer.h"USING_NS_CC;class MakeJson : public Ref{public: CREATE_FUNC(MakeJson); virtual bool init(); std::string getTestJson(); };#endif /* defined(__cpp4__MakeJson__) */
MakeJson.cpp
//// MakeJson.cpp// cpp4//// Created by 杜甲 on 14-9-9.////#include "MakeJson.h"bool MakeJson::init(){ bool bRef = false; do { bRef = true; } while (0); return bRef;}std::string MakeJson::getTestJson(){ rapidjson::Document d1; d1.SetObject(); rapidjson::Document::AllocatorType& allocator = d1.GetAllocator(); rapidjson::Value array(rapidjson::kArrayType); rapidjson::Value object(rapidjson::kObjectType); // object.AddMember("id", 1, allocator);// object.AddMember("name", "xiaonan", allocator);// object.AddMember("age", "111", allocator);// array.PushBack(object, allocator); d1.AddMember("reciver", "111", allocator); d1.AddMember("sender", "111", allocator); d1.AddMember("content", "神奇dfsa", allocator); // d1.AddMember("player", array, allocator); rapidjson::StringBuffer buffer; rapidjson::Writer<rapidjson::StringBuffer> write(buffer); d1.Accept(write); return StringUtils::format("%s",buffer.GetString()); }
0 0
- cocos2d-x3.2 Socket传输Json字符串
- Cocos2d-x3.0 Json解析
- Cocos2d-x3.0 Json解析
- cocos2d-x3.2入门
- cocos2d-x3.2 scrollView
- Cocos2d-x3.8.1网络编程(Socket)
- Cocos2d-x3.1生成Json串
- cocos2d-x3.4json动画删除问题
- Cocos2d-x3.8.1解析Json文件
- Socket传输字符串数组
- Cocos2d-x3.2环境搭建
- Cocos2d-x3.2 LayerMultiplex使用说明
- Cocos2d-x3.2 绘制线条
- Cocos2d-x3.2 双击事件
- Cocos2d-x3.2单点触摸
- Cocos2d-x3.2场景切换
- cocos2d-x3.2场景切换
- cocos2d-x3.2单点触摸
- Makefile 中的 ifeq 的缩进导致的错误
- Eclipse/ADT 卡在sdk content loader 0%的解决方法
- Android(安卓)WebView设置cookie
- svn is already locked解决方案
- Java调用C(Linux下实现Java本地方法)
- cocos2d-x3.2 Socket传输Json字符串
- DIV样式汇总
- Android 字体相关
- CentOS下手动Step By Step安装GitLab
- 两分钟彻底让你明白Android Activity生命周期(图文)
- js面向对象类
- 汉诺塔问题
- hdu 2846 Repository (字典树)
- 面试题1——Java的Exception和Error面试题10问10答