WebSocket引入protobuf协议

转载自:https://blog.csdn.net/iningwei/article/details/100107254

前言
nodejs游戏服务器开发系列文章以nodejs+Typescript+CocosCreator+WebSocket为例,搭建服务器和客户端。

protobuf
暂时无纯ts框架的pb库,一般会使用protobufjs,git地址:https://github.com/protobufjs/protobuf.js
同时也可以参考这个文档:https://www.npmjs.com/package/protobufjs

protobufjs有很多不同的版本(minimal,light,full),用户根据自己的项目需要选择合适的版本。各个版本的说明,可以参考git上readme.

建议不要使用git中releases的库,里面更新的慢。使用npm install protobufjs会把库下载到本地。可以看到CHANGELOG.md文档中写的是6.8.8.而在releases中最新的才6.8.6。

另外据说6以上版本protobufjs已经集成了long,bytebuffer库,不需要额外集成了。

本系列文章使用的是完整的protobufjs库(dist/protobuf.js)。

proto文件
搞个测试文件,比如命名为test.proto,内容为:

message user{
    required int32 userId=1;
    required string userName=2;
}

静态文件
推荐使用静态文件的方式,即预先把proto文件翻译为js文件。

需要全局安装pbjsnpm install protobufjs -g。可以使用pbjs命令用于把proto文件翻译为js静态文件。然后还可以使用pbts命令获得对应的声明文件*.d.ts

pbjs -t static-module -w commonjs -o proto.js *.proto
把目录下所有的proto文件一起生成静态文件到proto.js中

pbts -o proto.d.ts proto.js
为proto.js文件生成生命文件:proto.d.ts。

最终会生成proto.js和proto.d.ts文件

静态方式缺点,会额外生成静态文件,导致包体变大,特别是微信小游戏这种对包体敏感的平台。

服务端集成protobufjs
src目录下新建pb文件夹,把上述生成的静态文件proto.js,proto.d.ts和protobuf.js都放到pb文件夹中。

修改proto.js的var $protobuf = require("protobufjs/minimal");为var $protobuf = require("./protobuf");
修改proto.d.ts的第一句import * as $protobuf from "protobufjs";为import * as $protobuf from "./protobuf";

复制以下内容到 index.ts

import * as WebSocket from "ws"
import proto = require("./pb/proto");

const server = new WebSocket.Server({ port: 8083 });
server.on("listening", () => {
    console.log("服务器启动完毕!开始侦听");
});

server.on("connection", function connection(ws) {
    ws.on("message", function incoming(message) {
        console.log("received:%s", message);

        let u = proto.user.decode(<Uint8Array>message);
        console.log("decode, userid:" + u.userId + ", username:" + u.userName);
    });
    ws.send("hhhello");
});

服务端报错
ctrl+shift+b build的时候顺利。
Debug开启服务器的时候index.ts 报错:Error: Cannot find module ‘./pb/proto’
一开始一直在查模块方向的错误。
后面才恍然大悟:我服务器是用ts开发,最终生成的代码是在dist目录中。
编译的时候只是把ts代码编译到了dist目录,但是proto.js文件和protobuf.js文件我还放在src目录下的pb文件夹呢。

于是在dist目录中创建一个pb文件夹,同时把proto.js,protobuf.js拷贝过去,再次运行一切顺利。

客户端集成protobufjs
assets目录下新建文件夹:pb
把上述提到的protobuf.js放入pb目录下。设置导入为插件。同时还要勾选允许编辑器加载。
同时把proto.js和proto.d.ts放到pb目录下

CososCreator在构建时候会将我们编辑器里所有的js脚本都打包到一个project.js的文件中,原生(native)的话就是project.jsc。
如果我们的protobuf.js打包进去就会报错了,所以这里需要导入为插件,这样做就不会被打包进project.js文件中。

同时由于客户端中已经设置了插件模式。故proto.js中这句var $protobuf = require("protobufjs/minimal");需要改成:var $protobuf=protobuf;

还要修改proto.d.ts的第一句import * as $protobuf from "protobufjs";为import * as $protobuf from "./protobuf";

客户端代码如下:

    private ws: WebSocket;
    start() {
        console.log("go!");
        this.ws = new WebSocket("ws://192.168.2.31:8083");
        this.ws.binaryType="arraybuffer";        
        this.ws.onopen = this.onOpen.bind(this);
        this.ws.onmessage = function (event) {
            console.log("client rcv:" + event.data);
        }
        this.ws.onclose = function (event) {
        }.bind(this);
        this.ws.onerror = function (event) {
        }
    }


    private onOpen(event: MessageEvent) {
        console.log("连接建立啦");
        
        let u: user = new user()
        u.userId = 1;
        u.userName = "toms";
        
        let encoded = proto.user.encode(u).finish();
        this.sendData(encoded);

        let xxx = proto.user.decode(encoded);
        console.log("嘿嘿:" + xxx.userName);
    }
    private sendData(data) {
        this.ws.send(data);
    }

注意客户端设置了binaryType为arraybuffer(笔者注释了这行代码,也没有发现有啥问题)

需要注意:客户端decode后还要调用finish(),不然服务端那边解析不出来。

参考文档:
TS项目中使用Protobuf的解决方案

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值