• QQ
  • nahooten@sina.com
  • 常州市九洲新世界花苑15-2

Android

Cocos2d中的网络通讯协议——Socket通讯

原创内容,转载请注明原文网址:http://homeqin.cn/a/wenzhangboke/jishutiandi/Android/2019/1024/686.html

Cocos2d-X网络编程
 
Socket,俗称网络套接字,自身并不是协议,而是一个调用接口,是对TCP/IP协议的封装和应用,。常州手游开发提供了一系列办法便当开发者停止网络通讯。
TCP/IP协议是运用最早的通讯协议,它是传输层协议,主要处理数据如何在网络中传输。
Socket中又分为流形式与数据报形式,即TCP与UDP两种方式。
 
TCP : Transmission Control Protocol,传输控制协议,是面向衔接的协议,也就是说,在收发数据前,必需和对方树立牢靠的衔接。一个TCP衔接必需要经过三次“对话”才干树立起来,其中的过程十分复杂,但也是最平安的。
UDP : User Data Protocol,用户数据报协议。传输数据之前源端和终端不树立衔接,发送端直接把数据发送到网络,接纳端把音讯段放在队列中,应用程序每次从队列中读一个音讯段。
 
 
 
Socket根底和通讯流程:
Socket几个定义: 
1)IP地址:即按照TCP/IP协议分配给本地主机的网络地址,两个进程要通讯,任一进程首先要晓得通讯对方的位置,即对方的IP。
(2)端口号:用来区分本地通讯进程,一个本地的进程在通讯时均会占用一个端口号,不同的进程端口号不同,因而在通讯前必需要分配一个没有被访问的端口号。
(3)衔接:指两个进程间的通讯链路。
客户/效劳器形式:
在TCP/IP网络应用中,通讯的两个进程间互相作用的主要形式是客户/效劳器(Client/Server, C/S)形式,即客户向效劳器发出效劳恳求,效劳器接纳到恳求后,提供相应的效劳。
 
常州游戏开发培训Socket通讯流程:
server端:
1、效劳器端先初始化Socket
2、当一个套接字用socket()创立后,存在一个名字空间(地址族),但它没有被命名。bind()将套接字地址(包括本地主机地址和本地端口地址)与所创立的套接字号联络起来,行将名字赋予套接字,以指定本地半相关
3、对端口停止监听(listen)
4、调用accept阻塞,等候客户端衔接。
客户端:
1、客户端初始化一个Socket
2、然后衔接效劳器(connect)
3、假如衔接胜利,这时客户端与效劳器端的衔接就树立了。
4、客户端发送数据恳求(send),效劳器端接纳恳求并处置恳求,然后把回应数据发送给客户端,客户端读取数据。
5、最后关闭衔接,一次交互完毕。
 
 
 
 
 
cocos封装的3个Socket通讯相关类:
相似http,cocos2d对socket也停止了封装。提供了SocketIO,SIODelegate和SIOClient三个类。
SocketIO:
运用单例形式,初始化Socket,获取SIOClient。
 
SIODelegate: 
运用Socket协议,首先要继承SIODelegate,并且还要完成SIODelegate的4个虚函数
// 当翻开socket衔接时会调用这个函数
virtual void onConnect(cocos2d::network::SIOClient* client);
// 当接纳到数据时会调用这个函数
virtual void onMessage(cocos2d::network::SIOClient* client, const std::string& data);
// 当socket关闭时,会调用这个函数
virtual void onClose(cocos2d::network::SIOClient* client);
// 当衔接错误或接纳到错误信号时会调用这个函数
virtual void onError(cocos2d::network::SIOClient* client, const std::string& data);
 
SIOClient:
处置Socket的一系列动作,比方,发送数据,监听事情,断开衔接等
 
 
 
手机App外包发送事情和事情监听:
除了上面的发送Socket恳求外,Socket.io还提供了事情监听的机制,能够运用emit提交事情和数据,运用on监听事情和获取接纳到的数据。
比方客户端添加如下代码
client.emit("login","[{\"name\":\"myname\",\"pwd\":\"mypwd\"}]")
执行该代码后会向效劳端发送login事情,并把用户名和密码传送给效劳器。
效劳器端经过执行下面的代码,用来监听login事情,并获取传送过来的数据,然后在调用emit办法向客户端发送事情和数据。客户端运用on停止监听。这样就完成了客户端和效劳端之间的数据通讯。
socket.on('login', function(obj){
   //向一切客户端播送用户参加
   io.emit('loginresult', {message:'login success'});
  });
 
代码实操:
头文件:
 
#ifndef __TestSocketIo_SCENE_H__
#define __TestSocketIo_SCENE_H__
#include "cocos2d.h"
#include "network\SocketIO.h"
USING_NS_CC;
using namespace cocos2d::network;
class TestSocketIo : public cocos2d::Layer
,SocketIO::SIODelegate
{
public:
    static cocos2d::Scene* createScene();
    virtual bool init();
CREATE_FUNC(TestSocketIo);
    void menuCloseCallback(cocos2d::Ref* pSender);
 
    //继承和完成SIODelegate四个虚函数
void onConnect(SIOClient* client);
void onMessage(SIOClient* client, const std::string& data);
void onError(SIOClient* client, const std::string& data);
void onClose(SIOClient* client);
// 创立Socket
SIOClient *client;
 
};
#endif // __TestSocketIo_SCENE_H__
源文件:
 
#include "TestSocketIoScene.h"
Scene* TestSocketIo::createScene()
{
    auto scene = Scene::create();
    auto layer = TestSocketIo::create();
    scene->addChild(layer);
    return scene;
}
bool TestSocketIo::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
Size size = Director::getInstance()->getWinSize();
client = nullptr;
auto menu = Menu::create();
menu->setPosition(Vec2::ZERO);
addChild(menu);
auto lblInit = Label::create("init socket","Arial",22);
auto menuInit = MenuItemLabel::create(lblInit,[=](Ref *sender){
// 初始化
client = SocketIO::connect("ws://192.168.1.102:3000", *this);
// 设置tag辨别不同恳求
client->setTag("init socket");
 
// 运用Socket.io提供的on监听事情
client->on("loginresult",[=](SIOClient *client,const std::string &data){
log("login result is :%s",data.c_str());
});
});
menuInit->setPosition(size/2);
menu->addChild(menuInit);
auto lblSend = Label::create("send message","Arial",22);
auto menuSend = MenuItemLabel::create(lblSend,[=](Ref *sender){
// 发送恳求
client->send("hello socket.io");
});
menuSend->setPosition(size.width/2,size.height/2-50);
menu->addChild(menuSend);
auto lblSendEvent = Label::create("emit event","Arial",22);
auto menuSendEvent = MenuItemLabel::create(lblSendEvent,[=](Ref *sender){
// 运用Socket.io提供的emit提交事情
client->emit("login","[{\"name\":\"myname\",\"pwd\":\"mypwd\"}]");
});
menuSendEvent->setPosition(size.width/2,size.height/2-100);
menu->addChild(menuSendEvent);
    return true;
}
void TestSocketIo::onConnect(SIOClient* client){
log("onConnect");
log("%s connect",client->getTag());
}
void TestSocketIo::onMessage(SIOClient* client, const std::string& data){
log("onMessage");
log("%s received content is:%s",client->getTag(),data.c_str());
}
void TestSocketIo::onClose(SIOClient * client){
log("onClose");
log("%s is closed",client->getTag());
}
void TestSocketIo::onError(SIOClient* client, const std::string& data){
log("onError");
log("%s error is:%s",client->getTag(),data.c_str());
}
效劳器端:运用的node.js
 
var io = require('socket.io').listen(3000,'192.168.1.102');
console.log('Server on port 3000...');
io.sockets.on('connection',function(socket)
{
    //向客户端发送音讯
    socket.send('Hello Cocos2d-x');
    //注册message事情
    socket.on('message',function(data)
    {
        console.log(data);
    });
    //注册callServerEvent事情,便于客户端调用
    socket.on('login',function(data0)
    {
        console.log(data0);
        //向客户端发送音讯,触发客户端的callClientEvent事情
        socket.emit('loginresult',{message:'login success'});
    });
});
 


上篇:上一篇:android百度地图定位表现目前位置(android百度地图
下篇:下一篇:u3d怎样完成一个3D模型漂浮,上下浮动的效果