iohao / ioGame

无锁异步化、事件驱动架构设计的 java netty 网络编程框架; 轻量级,无需依赖任何第三方中间件或数据库就能支持集群、分布式; 适用于网络游戏服务器、物联网、内部系统及各种需要长连接的场景; 通过 ioGame 你可以很容易的搭建出一个集群无中心节点、集群自动化、分布式的网络服务器;FXGL、Unity、UE、Cocos Creator、Godot、Netty、Protobuf、webSocket、tcp、socket;java Netty 游戏服务器框架;
http://game.iohao.com
GNU Affero General Public License v3.0
904 stars 201 forks source link

关于改造现有或老客户端项目到ioGame遇到的问题 #198

Closed gkdiorflpgh04 closed 1 year ago

gkdiorflpgh04 commented 1 year ago

作为一个服务端开发者,想把客户端老项目升级改造为iogame时候,可能会遇到以下问题 1.没有权限修改客户端代码 2.客户端老架构不好改动,费时费力

于是萌生了不改动客户端现有通讯协议,而是在iogame框架的对外服中做兼容层的想法

具体做法是通过MicroBootstrapFlow,重写一个TcpExternalCodec,对客户端传来的数据进行转义,翻译为ExternalMessage

但是在实施的过程中,遇到了以下问题:

原始客户端的通讯格式为:

Message {
    int cmd;
    int subCmd;
    string tip;
    byte[] data;
}

对于cmd,subCmd,data,我们都能很好的转换为ExternalMessage的对应字段。 但是这里多了一个string类型的tip字段,该字段存在消息头中,客户端服务端都可以设置。

这样就产生了一个问题,我们在使用iogame的时候,在逻辑服我们无法获取或者设置这个tip字段。 但是为了兼容老客户端,我们又必须在逻辑服对这个字段进行读取或者赋值,在对外服再对这个字段进行编码和解码。

简单的总结就是: 对于单次请求,除了byte[] data,我们无法设置和读取其他私有的数据。

这个问题对于全新用iogame开发的项目来说,并没有任何影响,因为可以改造客户端协议进行支持。 但如果想兼容老客户端的话,目前iogame框架似乎还没有解决方案。

iohao commented 1 year ago

好的,明白了。

iohao commented 1 year ago

作为一个服务端开发者,想把客户端老项目升级改造为iogame时候,可能会遇到以下问题 1.没有权限修改客户端代码 2.客户端老架构不好改动,费时费力

于是萌生了不改动客户端现有通讯协议,而是在iogame框架的对外服中做兼容层的想法

具体做法是通过MicroBootstrapFlow,重写一个TcpExternalCodec,对客户端传来的数据进行转义,翻译为ExternalMessage

但是在实施的过程中,遇到了以下问题:

原始客户端的通讯格式为:

Message {
  int cmd;
  int subCmd;
  string tip;
  byte[] data;
}

对于cmd,subCmd,data,我们都能很好的转换为ExternalMessage的对应字段。 但是这里多了一个string类型的tip字段,该字段存在消息头中,客户端服务端都可以设置。

这样就产生了一个问题,我们在使用iogame的时候,在逻辑服我们无法获取或者设置这个tip字段。 但是为了兼容老客户端,我们又必须在逻辑服对这个字段进行读取或者赋值,在对外服再对这个字段进行编码和解码。

简单的总结就是: 对于单次请求,除了byte[] data,我们无法设置和读取其他私有的数据。

这个问题对于全新用iogame开发的项目来说,并没有任何影响,因为可以改造客户端协议进行支持。 但如果想兼容老客户端的话,目前iogame框架似乎还没有解决方案。

在 ExternalMessage 中添加了一个 customData 字段;开发者可以利用该字段来传递自定义数据到业务逻辑服; https://github.com/game-town/ioGame/blob/0d8c463610a15042e2bc0ca320c3c55eb7bf1e47/external/external-core/src/main/java/com/iohao/game/external/core/message/ExternalMessage.java#L81-L89

开发者可以通过 HeadMetadata customData 得到 ExternalMessage customData 中自定义的数据。

https://github.com/game-town/ioGame/blob/0d8c463610a15042e2bc0ca320c3c55eb7bf1e47/common/common-core/src/main/java/com/iohao/game/action/skeleton/protocol/HeadMetadata.java#L151-L158

使用示例

@ActionController(1)
public class MyAction {
    @ActionMethod(1)
    public String hello(FlowContext flowContext) {
        var headMetadata = flowContext.getRequest().getHeadMetadata();
        // 获取自定义数据
        byte[] customData = headMetadata.getCustomData();
        System.out.println(customData);

        String tip = "hello";
        // 注意,这里是随意写的伪代码
        headMetadata.setCustomData(tip.getBytes());

        return "";
    }
}

配合自定义 FlowContext 并扩展

https://www.yuque.com/iohao/game/zz8xiz#sLySn 配合上自定义 FlowContext,可以在使用上更简单。

@ActionController(1)
public class MyAction {
    @ActionMethod(1)
    public String hello2(MyFlowContext flowContext) {
        flowContext.setTip("hello");
        return "";
    }
}

public class MyFlowContext extends FlowContext {
    public void setTip(String tip) {
        HeadMetadata headMetadata = this.getRequest()
                .getHeadMetadata();
        // 注意,这里是随意写的伪代码
        // 设置自定义数据
        headMetadata.setCustomData(tip.getBytes());
    }
}

小结

开发者所设置的 HeadMetadata customData 数据,会透传到游戏对外服的 ExternalMessage 中;与 ExternalMessage msgId 特性类似。