FireFly菜鸟学习二(cocos2dx客户端和服务器通信实现)

2023-10-30

1.FireFly服务器

FireFly自定义通信协议。
      
#coding:utf8

from firefly.server.globalobject import netserviceHandle
from firefly.server.globalobject import GlobalObject
from firefly.netconnect.datapack import DataPackProtoc

#丢失链接调用
def callWhenConnLost(conn):
	dynamicId = conn.transport.sessionno
	GlobalObject().remote['gate'].callRemote("NetConnLost_2",dynamicId)

def CreatVersionResult(netversion):
    return netversion

def doConnectionMade(conn):
    print '已成功建立一个链接'
    
#返回客户端数据信息
def callbackSingleClientData(_conn, callbackstr):						
	GlobalObject().netfactory.pushObject(2, callbackstr, [_conn.transport.sessionno])


#定义协议信息
dataprotocl = DataPackProtoc(78,37,38,48,9,0)  
GlobalObject().netfactory.setDataProtocl(dataprotocl)  
  
GlobalObject().netfactory.doConnectionLost = callWhenConnLost  
GlobalObject().netfactory.doConnectionMade = doConnectionMade  
  
from firefly.server.globalobject import remoteserviceHandle  
from firefly.server.globalobject import netserviceHandle  


#与客户端通信消息 echo_1 后面的 1 为客户端发送的消息
@netserviceHandle
def echo_1(_conn,data):
    return data
@netserviceHandle
def echo_2(_conn,showtext):
	print showtext
	returnStr = '123'
	return callbackSingleClientData(_conn,returnStr)

    

上面还定义了一个名为echo_1的函数,后面这个_1是Firefly用识别功能函数的ID,绝对不能重复,当我们从客户端发送消息时,如果指定commandId参数为1,则服务端在接收到这个消息时,会执行echo_1这个函数,执行完后的return用来把返回给客户端相应的数据,服务端的代码就算是这样完成了。

2.cocos2dx客户端

了解基本的socket通信。

socket最核心的三个方法就是:

connect() 用于链接服务器

send() 用于发消息到服务器

recv() 用于接收服务器返回的消息

客户端发送的消息格式必须与Firefly的消息格式一致:发送给Firefly服务端的消息中需要包含以下头部信息

在发送的数据之前加上包头。为了做分包的处理。包头中包含了

HEAD_0,------char,字节数 1

HEAD_1,------char,字节数1

HEAD_2,------char,字节数1

HEAD_3,------char,字节数1

ProtoVersion,------char,字节数1

ServerVersion,------int,字节数4

length,-------int,字节数4(command+数据,总长度)

command,------int,字节数4(指令号)

协议头的总长度 17字节

下面就是发送的数据了。然后把协议头和发送的数据拼接发送。官网提供了很多游戏实例源码。
#include "cocos2d.h"
using namespace cocos2d;

typedef signed char byte;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_CONNECT_FAIL = 0xfffffA01;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_CONNECT_TERMINATE = 0xfffffA02;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_SERVER_CLOSE_CONNECTION = 0xfffffA03;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_CANNOT_SEND_MESSAGE = 0xfffffA04;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_IDLE_TIMEOUT = 0xfffffA05;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_RECONNECT_HINT = 0xfffffA06;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_RECONNECT_FORCE = 0xfffffA07;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_ERROR_MESSAGE = 0xfffffA08;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_CLIENT_KILL_MESSAGE = 0xfffffA09;

class Message:public CCObject
{
public:
    
    char HEAD0;
    char HEAD1;
    char HEAD2;
    char HEAD3;
    char ProtoVersion;
    
    byte serverVersion[4];
    byte length[4];
    byte commandId[4];
    
    char* data;
    
    Message();
    int datalength();
    ~Message();
};

再看看消息构造函数,这个也是取自Firefly官方发布的游戏源代码:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Message* networkManager::constructMessage(const char* data,int commandId)  
  2. {  
  3.     Message* msg = new Message();  
  4.       
  5.     msg->HEAD0=78;  
  6.     msg->HEAD1=37;  
  7.     msg->HEAD2=38;  
  8.     msg->HEAD3=48;  
  9.     msg->ProtoVersion=9;  
  10.       
  11.     int a=0;  
  12.     msg->serverVersion[3]=(byte)(0xff&a);;  
  13.     msg->serverVersion[2]=(byte)((0xff00&a)>>8);  
  14.     msg->serverVersion[1]=(byte)((0xff0000&a)>>16);  
  15.     msg->serverVersion[0]=(byte)((0xff000000&a)>>24);  
  16.       
  17.     int b=strlen(data)+4;  
  18.       
  19.     msg->length[3]=(byte)(0xff&b);;  
  20.     msg->length[2]=(byte)((0xff00&b)>>8);  
  21.     msg->length[1]=(byte)((0xff0000&b)>>16);  
  22.     msg->length[0]=(byte)((0xff000000&b)>>24);  
  23.       
  24.     int c=commandId;  
  25.     msg->commandId[3]=(byte)(0xff&c);;  
  26.     msg->commandId[2]=(byte)((0xff00&c)>>8);  
  27.     msg->commandId[1]=(byte)((0xff0000&c)>>16);  
  28.     msg->commandId[0]=(byte)((0xff000000&c)>>24);  
  29.       
  30.     //    str.append(msg->HEAD0);  
  31.     printf("%d" ,msg->datalength());  
  32.     msg->data = new char[msg->datalength()];  
  33.     memcpy(msg->data+0,&msg->HEAD0,1);  
  34.     memcpy(msg->data+1,&msg->HEAD1,1);  
  35.     memcpy(msg->data+2,&msg->HEAD2,1);  
  36.     memcpy(msg->data+3,&msg->HEAD3,1);  
  37.     memcpy(msg->data+4,&msg->ProtoVersion,1);  
  38.     memcpy(msg->data+5,&msg->serverVersion,4);  
  39.     memcpy(msg->data+9,&msg->length,4);  
  40.     memcpy(msg->data+13,&msg->commandId,4);  
  41.     memcpy(msg->data+17,data,strlen(data));  
  42.     //memcpy(msg->data+position,bytes+offset,len);  
  43.     //msg->data = data;  
  44.     return msg;  
  45. }  
上面的代码对消息从头到尾按次序进行了一次拼接封装,算是打包进data中,让其成为一个完整的数据包,最后返回消息对象。

然后就是链接服务器了,下面是代码:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //连接服务器

    bool networkManager::Connect() {

        mLock.lock();

        if(Init()==-1){

            return false;

        }

        if(Create(AF_INET,SOCK_STREAM,0)==false){

            return false;

        };


        struct sockaddr_in svraddr;

        svraddr.sin_family = AF_INET;

        svraddr.sin_addr.s_addr =inet_addr(IP_ADDRESS);

        svraddr.sin_port = htons(IP_HOST);

        int ret = connect(m_sock, (structsockaddr*) &svraddr, sizeof(svraddr));

        if (ret == SOCKET_ERROR) {

            return false;

        }

        sendThread();

        CCLOG("link successed");

        mLock.unlock();

        return true;

    } 


可以看到上面链接代码的尾部已经加入执行了发送数据的函数,发送的实现代码其实很简单,下面是发送了一条"getSendMessage successful!"的信息给服务器,而如果服务器收到这个消息后,也会在log里输出这样一条消息的:
void networkManager::sendThread(){
    Message* msg=constructMessage("getSendMessage successful!",2);
    Send(msg->data,msg->datalength(),0);
}


发送消息后,则可以开始监听接收服务端返回的数据了,下面只给出了基本代码,不包含数据解析,收到服务端返回的消息后可以看到LOG输出的信息:
//接收数据
void networkManager::RecvFunc(){
    char recvBuf[200];
    FD_ZERO(&fdRead);
    FD_SET(m_sock,&fdRead);
    mLock.lock();
    struct timeval	aTime;
    aTime.tv_sec = 5;
    aTime.tv_usec = 0;
    //Select在Socket编程中还是比较重要的,它能够监视我们需要监视的文件描述符的变化情况——读写或是异常。
    
    int ret = select(m_sock+1,&fdRead,NULL,NULL,&aTime);
    CCLog("socket State=%d",ret);
    if(ret==-1){
        log("socket error");
    }
    if(ret==0){
        printf("selector timeout . continue select.... \n");
    }
    if (ret > 0 )
    {
        if (FD_ISSET(m_sock,&fdRead))
        {
            int getRevDataLength=recv(m_sock,recvBuf,200,0);
            CCLOG("recvThread OK,getDataProcess=%d",getRevDataLength);
            if (getRevDataLength>17) {
                //前17个协议字段相关信息
                for (int i=0; i<17; i++) {
                    log("recv = %d",recvBuf[i]);
                }
                //后面为data信息打印查看
                for (int i=17; i<getRevDataLength; i++) {
                    log("recv = %c",recvBuf[i]);
                }
            }
        }
        
    }
    mLock.unlock();
}

启动服务器客户端完成通信。

原文链接: http://blog.csdn.net/cyistudio/article/details/39805749
相关下载:



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FireFly菜鸟学习二(cocos2dx客户端和服务器通信实现) 的相关文章

  • 【华为OD统一考试B卷

    在线OJ 已购买本专栏用户 请私信博主开通账号 在线刷题 运行出现 Runtime Error 0Aborted 请忽略 华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一
  • GLSL ES中的布局限定符(layout)

    一 存储限定字 首先需要了解存储限定字才能正确认识布局限定符 在webGL中要实现着色器和JS代码之间的数据交互 主要靠三类变量 分类的依据是存储限定字 分别是 attribute uniform varying 其中attrbute和un
  • 校招笔试面试---算法题1

    牛牛取快递 dijkstra 邻接表存图 优先队列 链接 https www nowcoder com questionTerminal 071695ed1d0b4e65b07eb969d212b92a 来源 牛客网 时间限制 1秒 空间限
  • 用批处理完全卸载mysql,完全卸载mysql(停止服务、卸载相关程序、删除注册表

    1 停止服务MySQL 2 卸载mysql相关的程序 3 删除注册表 运行 gt regedit machine gt system gt controlset001 controlset002 currentcontrolset gt s
  • Qt5下遍历QList的方法

    lines定义如下 QMap
  • 阿波罗无法通过链接外网

    官方提供说明 官方地址 无法连接外网的原因通常是阿波罗走到内网 通过注册中心无法连接到服务 bin bash apollo config db info apollo config db url jdbc mysql localhost 3
  • 【C++】初级—类和对象之赋值运算符重载、取地址操作符重载和const修饰的取地址运算符重载

    在上一篇中写到 一个类会产生的6种默认函数中的前三个默认函数 1 构造函数 2 析构函数 3 拷贝构造函数 4 赋值运算符重载 5 取地址操作符重载 6 拷贝构造函数 这次将着重讲解后三个函数 赋值运算符重载 运算符重载 什么是运算符重载呢
  • CSS字体的单位

    长度单位 1 像素 px 实际上是屏幕上的一个个小点 100px 100个小点 这个点 正常情况我们是看不到 如果我们把一个内容放大很多倍 就可以看到了 在pc端 电脑端 一般情况下1px 1个发光点 也是我们最常用的长度单位 它是固定单位
  • “区块链”技术在传统行业中的应用

    点击上方 中兴开发者社区 关注我们 每天读一篇一线开发者原创好文 比特币可能是一场庞氏骗局 但区块链技术却真实存在 2013年以来 比特币受到了全世界投资者的狂热追捧 虽然几经涨跌 大部分国家监管方对其态度也不甚明朗 但作为比特币底层技术的
  • react hooks实现原理(useState为例)

    一 源代码 逻辑十分绕 建议多敲几遍 let isMount true 判断是挂载还是更新 let workInProgressHook App组件对应的fiber对象 const fiber memorizedState null 当前h
  • 【NLP】T5:文本到文本转换器

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • 智能指针类HasPtr

    智能指针是存储指向动态分配对象指针的类 用于控制对象的生存期 能够确保自动正确的销毁动态分配的对象 防止内存泄露 HasPtr 在其他方面的行为与普通指针一样 具体而言 复制对象时 副本和原对象将指向同一基础对象 如果通过一个副本改变基础对
  • 微信小程序车牌号码输入(虚拟键盘)

    近日在网上看到一位博主写的微信小程序 输入车牌号 有新能源 原文链接 https blog csdn net qq706352062 article details 105554453 ops request misc 257B 2522r
  • ppt复现CVPR顶会流程图

    本次目标如下图 难点在于立方体和矩阵格网的绘制 文末附机器学习绘图模板 先来绘制立方体 插入 形状 立方体 调节成如下图 再点击水平翻转 绘制矩形 多绘制几个组合成矩形格网 右键设置形状和格式 输入以下参数 调整好使其贴合立方体 如图所示
  • 全志V3S环境编译开发流程

    这里使用的是荔枝派Zero 官网上面没有带spiflash的 首先准备一张SD卡 U BOOT 首先需要配置交叉编译环境 这里就不多说了 需要的话前往Sipeed官网 Sipeed 首先获取uboot源码 git clone https g
  • vscode快捷键:定位某一行,跳转到这一行

    快捷键 Ctrl G 然后在弹出的框中输入行数就可以了 参考 https blog csdn net cvper article details 81090028
  • Spring的三种注入方式:构造方法注入,set方法注入,注解注入

    本文演示三种值注入方式和三层模式下的注解注入获取对象 首先是搭建基本的Spring运行环境导入四个基本的核心jar包和两个日志包 在src根目录下新建bean xml的配置文件 同时引入dtd约束 一 构造函数注入 在bean xml中配置

  • 分割线样式

    hr style height 2px border none border top 2px ridge green
  • vue项目 后端传给base64格式图形验证码 ,前端进行解析,回显。

    我们在实际项目中时在登录的时候 时常会遇到图形验证码 来进行验证用户操作 什么是图形验证码 图形验证码是验证码的一种 有防止黑客对某一特定注册用户用程序暴力破解私人信息 恶意破解密码 刷论坛灌水的作用 票 图形验证码是一种区分用户是计算机还

随机推荐

  • SpringBoot底层原理

    SpringBoot底层原理 一 SpringBoot是什么 二 SpringBoot核心原理 三 springboot启动原理 一 SpringBoot是什么 想要了解springboot底层原理必须要先知道springboot是什么 作
  • 计算机视觉领域关注的会议和期刊

    原本为给师弟师妹总结的自己经验 节省计算机视觉领域大家看什么论文和去哪里看论文的困惑 一 会议论文 视觉的领域主要关注的三大顶会论文 CVPR ICCV ECCV 搜索途径 1 CVPR和ICCV都是IEEE库 可以在IEEE explor
  • QT中ui文件生成关联的C++类

    在VS2008中给对话框资源添加关联的C 类时 可通过右键菜单 添加类 直接添加关联的C 类 但QT中不支持这样的操作 在QT中在创建界面ui时 可手动也可自动创建ui文件关联的C 类 分别如下所示 一 自动创建ui文件和对应的C 类 项目
  • C语言开发网站

    在正式开发之前 先了解一下网站的原理 请求 处理 响应 在浏览器的network中可以看到浏览器和服务器的交互过程 请求一个网站的本质就是咱们的浏览器和服务器交互的一个过程 比如说咱们请求www baidu com 就是咱们的浏览器向服务器
  • lede 插件_路由器帮你签到!「LEDE/Openwrt系统“签到狗”插件使用教程」

    每日签到 废话不多说 用了才知道 图标 支持的站点 baidu 百度贴吧 百度文库v2ex V2EXhostloc hostloc comacfun A站bilibili B站163music 网易云音乐PCmiui 小米论坛52pojie
  • getline函数

    在我的印象中 getline函数经常出现在自己的视野里 模糊地记得它经常用来读取字符串 但是又对它的参数不是很了解 今天又用到了getline函数 现在来细细地总结一下 首先要明白设计getline函数的目的 其实很简单 就是从流中读取字符
  • 超强大JS表格:DataViewsJS 1.8.16.1407 Crack

    DataViewsJS完整的 JavaScript 数据呈现和数据网格平台 通过从各种不同的演示视图中进行选择 包括树 卡片 砖石 网格 时间线 甘特图 日历和网格 超越传统的表格显示 快速地 纯 JavaScript 针对速度进行了优化
  • ECMAScript 6规范总结(长文慎入)

    闲话 学习ES6的动机起于对其promise标准的好奇 它与jQuery源码中Deferred不同 而且在异步编程中加入了Generator 在后续ES7中更有Async 这勾起我强烈的兴趣了解ES6更多的内容 于是完整的学习了阮一峰老师的
  • Java Web实战开发基础:MVC模式

    Java Web的MVC模式 MVC是java web的基础 我写的java web实战开发专栏系列都是基于MVC 建议有需要的订阅我专栏的铁铁先提前看看这篇博文哦 简介 Java Web开发中 采用MVC Model View Contr
  • 【华为OD统一考试B卷

    在线OJ 已购买本专栏用户 请私信博主开通账号 在线刷题 运行出现 Runtime Error 0Aborted 请忽略 华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一
  • 进程间同步(互斥量、信号量)

    进程间同步可以使用互斥量mutex 互斥锁 信号量和文件锁 进程间同步使用信号量 int sem init sem t sem int pshared unsigned int value 用于进程间同步此时第二个参数不能取0了 取非0值用
  • stm32中can通讯的基本概念

    身为一个电控组的成员 我们当接触一个新的概念的时候首先应该去了解他的硬件 其次再者是软件 而且在学习新的应用时 也应该清楚什么我们要着重了解 什么我们要清楚即可 以can为例 我们先从他的硬件说起 Can硬件一共有两种接法 但核心还是两根信
  • Tomcat服务器的HTTP首部长度最大值

    今天编写Cas5 OAuth2 0 实现password 授权功能时 Tomcat 提示如下信息 HTTP 头部长度超出默认长度 解决方法 配置文件路径 TOMCAT HOME conf server xml 修改如下 添加头部最大值 81
  • 1一个HTTP请求的网络脉络,解压爽文

    一个HTTP请求的网络脉络 解压爽文 1写前的话 2 网络请求概览 2 1 http 的产生 2 1 1什么叫做协议 2 1 2http定义 2 1 3 http诞生历史 怎么来的 时间迭代史 2 1 4浏览器的小插曲 2 2tcp ip协
  • 开发者入门必读:最值得看的十大机器学习公开课

    转 http www leiphone com news 201701 0milWCyQO4ZbBvuW html 导语 入门机器学习不知道从哪着手 看这篇就够了 在当下的机器学习热潮 人才匮乏十分显著 截至目前 国内开设人工智能 AI 专
  • R语言时间序列之ARMA、ARIMA模型

    基本理论知识 ARMA模型称为自回归移动平均模型 是时间序列里常用的模型之一 ARMA模型是对不含季节变动的平稳序列进行建模 它将序列值表示为过去值和过去扰动项的加权和 模型形式如下 yt c a1yt 1 a2yt 2 apyt p t
  • 【图像识别】基于卷积神经网络CNN和支持向量机SVM实现花卉图像识别附matlab代码...

    作者简介 热爱科研的Matlab仿真开发者 修心和技术同步精进 matlab项目合作可私信 个人主页 Matlab科研工作室 个人信条 格物致知 内容介绍 针对传统图像分类算法在泛化能力等方面存在的不足 结合当前的深度学习算法 提出一种基于
  • 显示器尺寸对照表_怎样知道自己的电脑显示器是多少寸的

    展开全部 直接测量显示器e5a48de588b662616964757a686964616f31333366303731对角线即可 不包括边框 测量结果除以2 45得数就是显示器尺寸 显示器 display 通常也被称为监视器 显示器是属于
  • 20个基于DPDK开源项目,建议收藏

    一 ANS DPDK 原生加速网络堆栈 ANS 加速网络堆栈 是DPDK本地TCP IP堆栈 也参考FreeBSD实现 ANS提供了一个与Intel DPDK一起使用的用户空间TCP IP堆栈 文件结构 ans 加速网络堆栈过程 librt
  • FireFly菜鸟学习二(cocos2dx客户端和服务器通信实现)

    1 FireFly服务器 FireFly自定义通信协议 coding utf8 from firefly server globalobject import netserviceHandle from firefly server glo