下载地址:http://files.cnblogs.com/elephant-x/TCPSocketLibs_V1.0.rar
这是自己封装的一个TCPSOCKET包,是独立于cocos2d-x的,使用的时候,请把该项目加入到cocos2d-x里面去,再在项目里面包含libSocket项目和libSocket.lib
1、独立线程接收,异步连接服务端,防止界面卡的情况。
2、支持WIN32和LINUX。
3、编译linux时,在项目的Android.mk文件里必须添加下面两行:
LOCAL_WHOLE_STATIC_LIBRARIES += socket_static
$(call import-module,../CustomLibs/libSocket)
如图:
4、在Application.mk里面加入-std=c++11,因为源代码里面用到了c++11(VS2012)才有的std::bind和std::function,不支持c++11以下的编译器
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -DCC_ENABLE_CHIPMUNK_INTEGRATION=1 -DCOCOS2D_DEBUG=1 -std=c++11
如果是c++11以下的编译器,可以参考:
“function对于回调函数、将操作作为参数传递等十分有用。它可以看做是C++98标准库中函数对象mem_fun_t, pointer_to_unary_function等的替代品。同样的,bind()也可以被看做是bind1st()和bind2nd()的替代品,当然比他们更强大更灵活。”
自行改写。。
使用例子代码,可以拷贝到HelloCpp项目里去测试。
.h
1 #ifndef __HELLOWORLD_SCENE_H__ 2 #define __HELLOWORLD_SCENE_H__ 3 4 #include "cocos2d.h" 5 #include "TCPSocket.h" 6 7 class GameScene : public cocos2d::CCLayer 8 { 9 public: 10 // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone 11 virtual bool init(); 12 13 // there's no 'id' in cpp, so we recommend returning the class instance pointer 14 static cocos2d::CCScene* scene(); 15 16 // a selector callback 17 void menuCloseCallback(CCObject* pSender); 18 // 注册单个协议回调函数(样例),参数:SOCKET_ID标识,数据包 19 void process_login(int _tag, WorldPacket & packet); 20 // 物品更新 21 void process_openbackpack(int _tag, WorldPacket & packet); 22 // 注册单个协议回调函数(样例),参数:SOCKET_ID标识,协议头,数据包 23 bool process_all(int _tag, int _cmd, WorldPacket & packet); 24 // 连接事件 25 void OnConnect(int _tag, bool isConnect); 26 // 断线事件 27 void onDisconnect(int _tag); 28 // implement the "static node()" method manually 29 CREATE_FUNC(GameScene); 30 }; 31 32 #endif // __HELLOWORLD_SCENE_H__
.cpp
1 #include "GameScene.h" 2 #include "AppDelegate.h" 3 #include "AppMacros.h" 4 USING_NS_CC; 5 6 CCScene* GameScene::scene() 7 { 8 // 'scene' is an autorelease object 9 CCScene *scene = CCScene::create(); 10 11 // 'layer' is an autorelease object 12 GameScene *layer = GameScene::create(); 13 14 // add layer as a child to scene 15 scene->addChild(layer); 16 17 // return the scene 18 return scene; 19 } 20 void GameScene::process_login(int _tag, WorldPacket & packet) 21 { 22 CCLOG("process_login len:%u", packet.size()); 23 // 定义协议包 24 WorldPacket newP; 25 newP.clear(); 26 newP.SetOpcode(0x00B6);// 设置协议头 27 newP << uint16(0x00B6) 28 << uint16(0);// 协议长度 29 newP.SetLength(newP.size());// 设置协议长度 30 sSocketMgr.SendPacket(1, &newP);// 发送数据 31 } 32 33 void GameScene::process_openbackpack(int _tag, WorldPacket & packet) 34 { 35 CCLOG("process_openbackpack len:%u", packet.size()); 36 } 37 38 bool GameScene::process_all(int _tag, int _cmd, WorldPacket & packet) 39 { 40 CCLOG("process_all _tag:%u, _cmd:%u, len:%u", _tag, _cmd, packet.size()); 41 return false; 42 } 43 44 void GameScene::OnConnect(int _tag, bool isConnect) 45 { 46 // 定义协议包 47 WorldPacket packet; 48 packet.clear(); 49 packet.SetOpcode(0x0010);// 设置协议头 50 packet << uint16(0x0010) 51 << uint16(0)// 协议长度 52 << uint8(1) 53 << uint8(0); 54 // 加入字符串数据(uint8表示字符串长度所占字节,此处为1字节) 55 packet.AppendPacketString<uint8>(std::string("aaa:88889083:d5956683c17d7e284d33ee295b277b52")); 56 packet.SetLength(packet.size());// 设置协议长度 57 sSocketMgr.SendPacket(1, &packet);// 发送数据 58 CCLOG("OnConnect:%u, isConnect[%u]", _tag, isConnect); 59 } 60 61 void GameScene::onDisconnect(int _tag) 62 { 63 CCLOG("desconnect:%u", _tag); 64 } 65 66 // on "init" you need to initialize your instance 67 bool GameScene::init() 68 { 69 ////////////////////////////// 70 // 1. super init first 71 if ( !CCLayer::init() ) 72 { 73 return false; 74 } 75 76 CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); 77 CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin(); 78 79 ///////////////////////////// 80 // 2. add a menu item with "X" image, which is clicked to quit the program 81 // you may modify it. 82 83 // add a "close" icon to exit the progress. it's an autorelease object 84 CCMenuItemImage *pCloseItem = CCMenuItemImage::create( 85 "CloseNormal.png", 86 "CloseSelected.png", 87 this, 88 menu_selector(GameScene::menuCloseCallback)); 89 90 pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 , 91 origin.y + pCloseItem->getContentSize().height/2)); 92 93 // create menu, it's an autorelease object 94 CCMenu* pMenu = CCMenu::create(pCloseItem, NULL); 95 pMenu->setPosition(CCPointZero); 96 this->addChild(pMenu, 1); 97 98 ///////////////////////////// 99 // 3. add your codes below... 100 101 // add a label shows "Hello World" 102 // create and initialize a label 103 104 CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", TITLE_FONT_SIZE); 105 106 // position the label on the center of the screen 107 pLabel->setPosition(ccp(origin.x + visibleSize.width/2, 108 origin.y + visibleSize.height - pLabel->getContentSize().height)); 109 110 // add the label as a child to this layer 111 this->addChild(pLabel, 1); 112 113 // add "HelloWorld" splash screen" 114 CCSprite* pSprite = CCSprite::create("HelloWorld.png"); 115 116 // position the sprite on the center of the screen 117 pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y)); 118 119 // add the sprite as a child to this layer 120 this->addChild(pSprite, 0); 121 /////////////////////////////////////////////// 122 // 创建SOCKET管理器 123 CREATE_TCPSOCKETMGR(); 124 uint64 t_begin = GetCurrentTime(); 125 // 创建并添加SOCKET,参数:服务器IP,端口,自定义的SOCKET_ID标识 126 sSocketMgr.createSocket("192.168.0.183", 7502, 1); 127 uint64 t_end = GetCurrentTime(); 128 // 注册协议,参数:包头,回调函数 129 sSocketMgr.register_process(0x10, SCT_CALLBACK_2(GameScene::process_login, this)); 130 sSocketMgr.register_process(0x2d, SCT_CALLBACK_2(GameScene::process_openbackpack, this)); 131 // 注册消息截获事件,注册此事件后可以截获收到的所有消息,若回调函数返回true则本次事件会继续分发注册过的协议,返回false则不分发 132 sSocketMgr.register_connect(SCT_CALLBACK_2(GameScene::OnConnect, this)); 133 sSocketMgr.register_disconnect(SCT_CALLBACK_3(GameScene::onDisconnect, this)); 134 135 136 CCLOG("GameScene::init end! [%u]", t_end - t_begin); 137 /////////////////////////////////////////////// 138 return true; 139 } 140 141 void GameScene::menuCloseCallback(CCObject* pSender) 142 { 143 #if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) 144 CCMessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert"); 145 #else 146 CCDirector::sharedDirector()->end(); 147 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) 148 exit(0); 149 #endif 150 #endif 151 }