2019独角兽企业重金招聘Python工程师标准>>>

flatbuffers 可以应用到游戏中。媲美google protobuffer。

https://github.com/google/flatbuffers

http://google.github.io/flatbuffers/index.html

下载flatbuffers 编译对应平台的flatc。

接下来是编写fbs:

namespace com.dc.gameserver.genflat;table LoginRequest{msgID:int=1;username:string;password:string;time:long;
}
///table LoginResponse{msgID:int=2;time:long;uid:string;
}

详细说明见:http://google.github.io/flatbuffers/md__schemas.html

flatc脚本方式:http://google.github.io/flatbuffers/md__compiler.html

flatc.exe  -j   -o ../../java/ game.fbs

会生成对应的java文件.

// automatically generated, do not modifypackage com.dc.gameserver.genflat;import com.google.flatbuffers.FlatBufferBuilder;
import com.google.flatbuffers.Table;import java.nio.ByteBuffer;
import java.nio.ByteOrder;public class LoginRequest extends Table {public static LoginRequest getRootAsLoginRequest(ByteBuffer _bb) { return getRootAsLoginRequest(_bb, new LoginRequest()); }public static LoginRequest getRootAsLoginRequest(ByteBuffer _bb, LoginRequest obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }public LoginRequest __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }public int msgID() { int o = __offset(4); return o != 0 ? bb.getInt(o + bb_pos) : 1; }public String username() { int o = __offset(6); return o != 0 ? __string(o + bb_pos) : null; }public ByteBuffer usernameAsByteBuffer() { return __vector_as_bytebuffer(6, 1); }public String password() { int o = __offset(8); return o != 0 ? __string(o + bb_pos) : null; }public ByteBuffer passwordAsByteBuffer() { return __vector_as_bytebuffer(8, 1); }public long time() { int o = __offset(10); return o != 0 ? bb.getLong(o + bb_pos) : 0; }public static int createLoginRequest(FlatBufferBuilder builder,int msgID,int username,int password,long time) {builder.startObject(4);LoginRequest.addTime(builder, time);LoginRequest.addPassword(builder, password);LoginRequest.addUsername(builder, username);LoginRequest.addMsgID(builder, msgID);return LoginRequest.endLoginRequest(builder);}public static void startLoginRequest(FlatBufferBuilder builder) { builder.startObject(4); }public static void addMsgID(FlatBufferBuilder builder, int msgID) { builder.addInt(0, msgID, 1); }public static void addUsername(FlatBufferBuilder builder, int usernameOffset) { builder.addOffset(1, usernameOffset, 0); }public static void addPassword(FlatBufferBuilder builder, int passwordOffset) { builder.addOffset(2, passwordOffset, 0); }public static void addTime(FlatBufferBuilder builder, long time) { builder.addLong(3, time, 0); }public static int endLoginRequest(FlatBufferBuilder builder) {int o = builder.endObject();return o;}
};
// automatically generated, do not modifypackage com.dc.gameserver.genflat;import com.google.flatbuffers.FlatBufferBuilder;
import com.google.flatbuffers.Table;import java.nio.ByteBuffer;
import java.nio.ByteOrder;///public class LoginResponse extends Table {public static LoginResponse getRootAsLoginResponse(ByteBuffer _bb) { return getRootAsLoginResponse(_bb, new LoginResponse()); }public static LoginResponse getRootAsLoginResponse(ByteBuffer _bb, LoginResponse obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }public LoginResponse __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }public int msgID() { int o = __offset(4); return o != 0 ? bb.getInt(o + bb_pos) : 2; }public long time() { int o = __offset(6); return o != 0 ? bb.getLong(o + bb_pos) : 0; }public String uid() { int o = __offset(8); return o != 0 ? __string(o + bb_pos) : null; }public ByteBuffer uidAsByteBuffer() { return __vector_as_bytebuffer(8, 1); }public static int createLoginResponse(FlatBufferBuilder builder,int msgID,long time,int uid) {builder.startObject(3);LoginResponse.addTime(builder, time);LoginResponse.addUid(builder, uid);LoginResponse.addMsgID(builder, msgID);return LoginResponse.endLoginResponse(builder);}public static void startLoginResponse(FlatBufferBuilder builder) { builder.startObject(3); }public static void addMsgID(FlatBufferBuilder builder, int msgID) { builder.addInt(0, msgID, 2); }public static void addTime(FlatBufferBuilder builder, long time) { builder.addLong(1, time, 0); }public static void addUid(FlatBufferBuilder builder, int uidOffset) { builder.addOffset(2, uidOffset, 0); }public static int endLoginResponse(FlatBufferBuilder builder) {int o = builder.endObject();return o;}
};

消息设计原则除了基础的游戏数据会有一个消息ID。

获取生成Table消息ID可以这样:

 LoginResponse.getRootAsLoginResponse(ByteBuffer.allocate(4)).msgID();

修改了下源码(Table),避免new一个ByteBuffer,可以这样

  // Look up a field in the vtable, return an offset into the object, or 0 if the field is not// present.protected int __offset(int vtable_offset) {if (bb == null) return 0; // get msgID  ,ignore allocate ByteBufferint vtable = bb_pos - bb.getInt(bb_pos);return vtable_offset < bb.getShort(vtable) ? bb.getShort(vtable + vtable_offset) : 0;}
new LoginResponse().msgID();

flatbuffer中有对默认的数值填充,将会不对其存储!。如没有默认值的字段都为0,不管基础数据类型还是string.;存在默认值如id:int=1;在填充数据value==1时,不会被存储。

反正默认值不被存储就对了,详见代码Table;当然可以强制进行存储,builder.setForcexx(true);

netty只负责网络传输。解析网络字节码就对了,根据协议包长+消息体(ID+游戏操作数据)。

针对java,采用多态的方式进行处理对应的消息体。

  static final IController game_controllers[] = new IController[2];

存储消息处理类的引用。

Controller接口设计:

/*** 基于flatBuffers 结构数据传输** @param data   cast subclass of table .* @param player game session* @throws Exception*/void DispatchFlatBuffer(final byte[] data, final PlayerInstance player) throws Exception;

实现类:

/** Copyright (c) 2015.* 游戏服务器核心代码编写人石头哥哥拥有使用权* 最终使用解释权归创心科技所有* 联系方式:E-mail:13638363871@163.com ;* 个人博客主页:http://my.oschina.net/chenleijava* powered by 石头哥哥*/package com.dc.gameserver.servercore.controller.testflatbuffercontroller;import com.dc.gameserver.genflat.LoginRequest;
import com.dc.gameserver.genflat.LoginResponse;
import com.dc.gameserver.model.character.PlayerInstance;
import com.dc.gameserver.servercore.controller.abstractController.AbstractController;
import com.google.flatbuffers.FlatBufferBuilder;
import com.google.protobuf.MessageLite;
import org.springframework.stereotype.Service;import java.nio.ByteBuffer;
import java.util.UUID;/*** @author 石头哥哥*         </P>*         Date:   2015/6/1*         </P>*         Time:   14:36*         </P>*         Package: dcServer-parent*         </P>*         <p/>*         注解: 测试flatbuf 转化到游戏逻辑处理*/
@Service
public class TestFlatBufferController extends AbstractController {/*** spring 容器初始化 加载并初始化相应控制器处理句柄* 非spring环境下 可以采用静态的初始化方案*/@Overridepublic void PostConstruct() {game_controllers[new LoginRequest().msgID()] = this;}/*** messageLite数据结构体分发** @param messageLite 数据载体* @param player      active object* @throws Exception 注意messageLite应该递交给GC直接处理  ,set null*/@Override@Deprecatedpublic void DispatchMessageLit(MessageLite messageLite, PlayerInstance player) throws Exception {}/*** 基于flatBuffers 结构数据传输** @param data   cast subclass of table .         msgID + 游戏数据(可反序列化为flatbuffers Table 子类 这里如LoginRequest)* @param player game session* @throws Exception*/@Overridepublic void DispatchFlatBuffer(byte[] data, PlayerInstance player) throws Exception {//4 为消息ID 所占用的位置LoginRequest login = LoginRequest.getRootAsLoginRequest(ByteBuffer.wrap(data, 4, data.length - 4));String username = login.username();String password = login.password();// do something// get msgIDint msgID = new LoginResponse().msgID();FlatBufferBuilder builder = new FlatBufferBuilder(8);builder.finish(LoginResponse.createLoginResponse(builder, msgID, System.currentTimeMillis(), builder.createString(UUID.randomUUID().toString())));wrappedBufferInt(msgID, builder);}public static void main(String[] args) {//builder data  and finish itint msgID = new LoginResponse().msgID();FlatBufferBuilder builder = new FlatBufferBuilder(8);builder.finish(LoginResponse.createLoginResponse(builder, msgID, System.currentTimeMillis(), builder.createString(UUID.randomUUID().toString())));wrappedBufferInt(msgID, builder);}}

由于flatbuf相对protobuffer 体积较小  在cocos2dx中应用 相对较为方便。  目前已经有一套完整的应用解决方案思路(前后端代码生成器)。欢迎交流!

转载于:https://my.oschina.net/chenleijava/blog/423503

flatbuffers 和netty的结合使用相关推荐

  1. 用netty实现zcool_Netty 如何玩转内存使用

    内存使用技巧的目标 目标: • 内存占用少(空间) • 应用速度快(时间) 对 Java 而言:减少 Full GC 的 STW(Stop the world)时间 Netty 内存使用技巧 - 减少 ...

  2. ktor框架用到了netty吗_教你如何构建异步服务器和客户端的 Kotlin 框架 Ktor

    Ktor 是一个使用 Kotlin 以最小的成本快速创建 Web 应用程序的框架. Ktor 是一个用于在连接系统(connected systems)中构建异步服务器和客户端的 Kotlin 框架. ...

  3. 实现分布式服务注册及简易的netty聊天

    现在很多地方都会用到zookeeper, 用到它的地方就是为了实现分布式.用到的场景就是服务注册,比如一个集群服务器,需要知道哪些服务器在线,哪些服务器不在线. ZK有一个功能,就是创建临时节点,当机 ...

  4. netty集成ssl完整参考指南(含完整源码)

    虽然我们在内部rpc通信中使用的是基于认证和报文头加密的方式实现安全性,但是有些时候仍然需要使用SSL加密,可能是因为对接的三方系统需要,也可能是由于open的考虑.中午特地测了下netty下集成ss ...

  5. Netty和JDK源码来看Netty的NIO和JDK的NIO有什么不同

    JDK底层提供了NIO实现,在Linux环境会调用内核epoll. 但是Netty通过JNI的方式提供了Native Socket Transport,为什么Netty要自己搞一套NIO呢? 这篇文章 ...

  6. 仿qq左滑删除listview_Java基于Swing和Netty仿QQ界面聊天小项目

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:硬刚一周,3W字总结,一年的经验告诉你如何准备校招! 个人原创100W+访问量博客:点击前往,查看更多 来源:b ...

  7. Netty - ByteBuf

    2019独角兽企业重金招聘Python工程师标准>>> 1.ByteBuf类 - Netty的数据容器 ByteBuf维护了两个不同的索引: readerIndex:用于读取 wri ...

  8. Netty 之 Zero-copy 的实现(下)

    上一篇说到了 CompositeByteBuf ,这一篇接着上篇的讲下去. FileRegion 让我们先看一个Netty官方的example // netty-netty-4.1.16.Final\ ...

  9. Netty 粘包 拆包 编码 解码 序列化 介绍

    目录: 粘包 & 拆包及解决方案 ByteToMessageDecoder 基于长度编解码器 基于分割符的编解码器 google 的 Protobuf 序列化介绍 其他的 前言 Netty 作 ...

最新文章

  1. Stack Overflow被收购了,以后要付费“抄代码”?
  2. 如何在 Linux 中查看目录大小?
  3. 【转载】2009年春晚节目单提前揭晓
  4. 小议传统分层与新式分层,抑或与DDD分层
  5. ftp4j jar maven依赖_maven系列--maven添加第三方、本地依赖
  6. 在线打假!“鲁迅说过的话”检索系统上线 网友太热情系统一度崩溃
  7. python怎么执行代码漏洞_如何使用python查找网站漏洞
  8. Node.js区块链开发pdf
  9. gcc -o sqlite3 shell.c sqlite3.c -ldl -lpthread
  10. obj 转为Json 时间格式自定义
  11. 04-初始mysql语句
  12. SpringBoot + Thymeleaf 练手小项目 --------- 豆瓣网站模拟
  13. DTI处理工具包PANDA小白记录
  14. 新手亲自踩坑!Jmter使用CSV Data Set Config配置原件测试登录接口,察看结果树无响应问题
  15. 活体检测 Face Anti-Spoofing Using TransformersWith Relation-Aware Mechanism 学习笔记
  16. 创建磁盘分区,创建逻辑卷组。
  17. keytool生成keystore、truststore、证书
  18. 低代码可以做什么?以织信informat这个平台为例说说
  19. 风险提醒之Oracle RAC高可用失效
  20. 设置输入框默认文字内容

热门文章

  1. 核心交换机的TRUNK配置功能详细讲解
  2. 无数优秀投资人的选择——GMQ Group
  3. 0717PHP基础:面向对象
  4. Java Web开发中文乱码问题
  5. 第62天:手风琴效果
  6. 轻松应对IDC机房带宽突然暴涨问题
  7. [NHibernate]基本配置与测试
  8. 【web安全】Xss Exploits and Defense翻译4
  9. 修改Android设备在Windows设备管理器出现的设备名称
  10. BCH为什么要把自身打造成多元化平台