本人之前一直想搞搞用cocos进行网络编程,也在网上逛了很久,但令人纳闷的是,网上的大牛们要么讲了些socket编程的原理,要么讲了些cocos2dx,socket的独特之处。但是作为一名菜鸟,能把程序跑起来,是最基本的一步,也是对自信心一个很大的鼓励。在网上找了很久,都 没有一整套完整的源码。小弟不才,自我摸索,搞了一个简单的tcp/ip协议的简单连接。
学习之些,对socket总得有一个基本的了解吧,此内容不少,给出一个别人的博客链接,大家可以先看看这篇博客。
socket基础学习
要进行socket编程,首先要有socket包,点击下载。该包是从别人来下载过来,别人已经封装好了,在windows下和linux下都能运行。
看完上面所给的博客后。我贴上我的代码。理工科,文章写得不好,尽量少费话,直接上代码。
客户端:
------------------------------------
#ifndef __Client_SCENE_H__ #define __Client_SCENE_H__ #include "cocos2d.h" #include "ODSocket/ODSocket.h" USING_NS_CC; enum GameState { GameState_init, GameState_finishset, GameState_null, }; class Client : public cocos2d::Layer { public: static cocos2d::Scene* createScene(); virtual bool init(); bool onTouchBegan(Touch* touch,Event *event); void onTouchEnded(Touch* touch,Event *event); void update(float dt); void menuCloseCallback(cocos2d::Ref* pSender); CREATE_FUNC(Client); void connectServer(const char * ip,int port); void connectServer(const char * ip,int port,const char* _infodata); void receiveData(); void SelectCallback1(Ref* pSender); void SelectCallback2(Ref* pSender); void SelectCallback3(Ref* pSender); void SelectCallback4(Ref* pSender); void SelectCallback5(Ref* pSender); private: ODSocket m_socket; cocos2d::TextFieldTTF* textEdit; GameState m_gamestate; bool m_setok; }; #endif // __Client_SCENE_H__
--------------------------------------------------------------------------------
#include "HelloWorldScene.h" USING_NS_CC; using namespace std; static const char* C_select[]= { "a","b","c","d" }; static const int C_selectNum = 4; Scene* Client::createScene() { auto scene = Scene::create(); auto layer = Client::create(); scene->addChild(layer); return scene; } bool Client::init() { if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); auto closeItem = MenuItemImage::create( "CloseNormal.png", "CloseSelected.png", CC_CALLBACK_1(Client::menuCloseCallback,this)); closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2, origin.y + closeItem->getContentSize().height/2)); auto menu = Menu::create(closeItem,NULL); menu->setPosition(Vec2::ZERO); this->addChild(menu,1); TTFConfig ttfConfig("fonts/arial.ttf",100); auto label_1 = Label::createWithTTF(ttfConfig,C_select[0]); auto menuItem_1 = MenuItemLabel::create(label_1,CC_CALLBACK_1(Client::SelectCallback1,this)); menu->addChild(menuItem_1,0); menuItem_1->setPosition(Vec2(1/5.0*visibleSize.width,400)); auto label_2 = Label::createWithTTF(ttfConfig,C_select[1]); auto menuItem_2 = MenuItemLabel::create(label_2,CC_CALLBACK_1(Client::SelectCallback2,this)); menu->addChild(menuItem_2,0); menuItem_2->setPosition(Vec2(2/5.0*visibleSize.width,400)); auto label_3 = Label::createWithTTF(ttfConfig,C_select[2]); auto menuItem_3 = MenuItemLabel::create(label_3,CC_CALLBACK_1(Client::SelectCallback3,this)); menu->addChild(menuItem_3,0); menuItem_3->setPosition(Vec2(3/5.0*visibleSize.width,400)); auto label_4 = Label::createWithTTF(ttfConfig,C_select[3]); auto menuItem_4 = MenuItemLabel::create(label_4,CC_CALLBACK_1(Client::SelectCallback4,this)); menu->addChild(menuItem_4,0); menuItem_4->setPosition(Vec2(4/5.0*visibleSize.width,400)); auto label_5 = Label::createWithTTF("ok","fonts/arial.ttf",30); auto menuItem_5 = MenuItemLabel::create(label_5,CC_CALLBACK_1(Client::SelectCallback5,this)); menu->addChild(menuItem_5,0); menuItem_5->setPosition(Vec2(400,100)); textEdit = CCTextFieldTTF::textFieldWithPlaceHolder("Please input ip:", "Arial",30); //设置文本框的位置 textEdit->setPosition(Vec2(100,100)); //添加文本框到层上 this->addChild(textEdit); //当触摸到控件的时候弹出软键盘 setTouchMode(kCCTouchesOneByOne); auto listener = EventListenerTouchOneByOne::create(); listener->onTouchBegan = CC_CALLBACK_2(Client::onTouchBegan,this); listener->onTouchEnded = CC_CALLBACK_2(Client::onTouchEnded,this); auto _eventDispatcher=Director::getInstance()->getEventDispatcher(); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this); m_gamestate = GameState_init; m_setok = false; this->scheduleUpdate(); //connectServer("127.0.0.1",9999,"client"); return true; } bool Client::onTouchBegan(Touch* touch,Event *event) { auto point=touch->getLocation(); if (textEdit->getBoundingBox().containsPoint(point) == true && m_gamestate == GameState_init) { textEdit->attachWithIME(); } return true; } void Client::onTouchEnded(Touch* touch,Event *event) { } void Client::update(float dt) { switch (m_gamestate) { case GameState_init: if (m_setok == true ) { m_gamestate=GameState_finishset; string m_text = textEdit->getString(); connectServer(m_text.c_str(),"client"); log("----------------------------------------input id is %s",m_text.c_str()); } break; case GameState_finishset: m_gamestate=GameState_null; break; case GameState_null: break; default: break; } } void Client::connectServer(const char * ip,const char* _infodata) { // 初始化 m_socket.Init(); m_socket.Create(AF_INET,SOCK_STREAM,0); // 设置服务器的IP地址,端口号 bool result = m_socket.Connect(ip,port); if (result) { // 发送数据 Send log("%s connect to server success!",_infodata); // 开启新线程,在子线程中,接收数据 //m_socket.Send(_infodata,11); //std::thread recvThread = std::thread(&HelloWorld::receiveData,this); //recvThread.detach(); // 从主线程分离 //receiveData(); } else { log("%s can not connect to server",_infodata); return; } //m_socket.Close(); } // 客户接收数据 void Client::receiveData() { // 因为是强联网,所以可以一直检测服务端是否有数据传来 while (true) { // 接收数据 Recv char data[512] = ""; int result = m_socket.Recv(data,512,0); //log("%d",result); // 与服务器的连接断开了 if (result <= 0) break; log("client receive:%s",data); } // 关闭连接 m_socket.Close(); } void Client::menuCloseCallback(Ref* pSender) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert"); return; #endif Director::getInstance()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif } void Client::SelectCallback1(Ref* pSender) { m_socket.Send(C_select[0],1); } void Client::SelectCallback2(Ref* pSender) { m_socket.Send(C_select[1],1); } void Client::SelectCallback3(Ref* pSender) { m_socket.Send(C_select[2],1); } void Client::SelectCallback4(Ref* pSender) { m_socket.Send(C_select[3],1); } void Client::SelectCallback5(Ref* pSender) { m_setok =true ; }
------------------------------------------------------------------------
服务器
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" #include "ODSocket/ODSocket.h" USING_NS_CC; enum game_state { game_state_init, game_state_getnext, gam_state_null, }; class HelloWorld : public cocos2d::Layer { public: static cocos2d::Scene* createScene(int _id); virtual bool init(int _id); static HelloWorld* create(int id); void menuCloseCallback(cocos2d::Ref* pSender); void connectServer(const char * ip,int port); void receiveData(); void server(); void update(float delta); void getNext(Ref* _sender); void startServer(); void stopServer(); private: Label* m_label; Label* m_result; ODSocket m_ServerSocket; game_state m_gamestate; std::string m_recData; }; #endif // __HELLOWORLD_SCENE_H__
-----------------------------------------------------------------
#include "HelloWorldScene.h" USING_NS_CC; using namespace std; static const char* C_select[]= { "a","d", }; static std::string _currentShowData="nothing"; Scene* HelloWorld::createScene(int id) { // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = HelloWorld::create(id); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } HelloWorld* HelloWorld::create(int id) { HelloWorld* _layer = new HelloWorld(); if (_layer && _layer->init(id)) { _layer->autorelease(); return _layer; }else { delete _layer; _layer =nullptr; return _layer; } } bool HelloWorld::init(int id) { if ( !Layer::init() ) { return false; } m_recData = ""; Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); auto closeItem = MenuItemImage::create( "CloseNormal.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback, origin.y + closeItem->getContentSize().height/2)); auto menu = Menu::create(closeItem,NULL); menu->setPosition(Vec2::ZERO); this->addChild(menu,1); auto next= Label::createWithTTF("next",50); auto menuItem_1 = MenuItemLabel::create(next,CC_CALLBACK_1(HelloWorld::getNext,0); menuItem_1->setPosition(Vec2(4/5.0*visibleSize.width,100)); TTFConfig ttfConfig("fonts/arial.ttf",100); m_label = Label::createWithTTF(ttfConfig,""); m_label->setPosition(Vec2(visibleSize.width/2,visibleSize.height/2)); this->addChild(m_label,1); m_result = Label::createWithTTF("",50); m_result->setPosition(Vec2(visibleSize.width/2,visibleSize.height/4)); this->addChild(m_result,1); m_result->setColor(Color3B(255,0)); m_gamestate = game_state_init; this->scheduleUpdate(); return true; } void HelloWorld::update(float delta) { std::thread recvThread; switch (m_gamestate) { case game_state_init: startServer(); m_gamestate=game_state_getnext; break; case game_state_getnext: recvThread = std::thread(&HelloWorld::server,this); recvThread.detach(); m_gamestate=gam_state_null; break; case gam_state_null: if (m_recData == _currentShowData) { m_result->setString("true"); } else { m_result->setString("false"); } break; default: break; } } void HelloWorld::startServer() { log("server init !"); m_ServerSocket.Init(); m_ServerSocket.Create(AF_INET,0); m_ServerSocket.Bind(9999); m_ServerSocket.Listen(5); } void HelloWorld::stopServer() { m_ServerSocket.Close(); } void HelloWorld::getNext(Ref* _sender) { _currentShowData= C_select[rand()%4]; m_label->setString(_currentShowData); //m_gamestate=game_state_getnext; } void HelloWorld::server() { m_ServerSocket.Accept(m_ServerSocket); log("server is ready !"); while (true) { char data[512] = ""; int result =m_ServerSocket.Recv(data,0 ); log("server receive:%s",data); m_recData=data; if (result<0) { break; } //m_ServerSocket.Send("helloclient",11); } //stopServer(); } void HelloWorld::menuCloseCallback(Ref* pSender) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert"); return; #endif Director::getInstance()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif }
----------------------------------------
上面主要是是socket编程中的TCP/IP,UDP正在更新中,尽请期待。。。。。 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|