Layaair Socket.io 的使用
- 客户端 使用Layaair 1.7.x 版本 socket.io.d.ts 是从 Egret 搬过来的, socket.io.js 库 是客户端 和 服务器公用的
- 服务器 nodejs
- 协议 protobuf
Socket.io 对比 Websocket 的优势太多了,但是Layaair 没有提供 对 Socket.io 的支持,所以呢 参照了 Egret ,应为用的传输 协议是protobuf ,
客户端和服务器 对 protobuf 的 .proto 的解析都是采用 静态解析,
对于Layaair 的 静态解析前面的博客有提到 不熟悉的同学可以参照下
https://blog.csdn.net/nicepainkiller/article/details/83115669
对于 nodejs 静态集成 protobuf 的 .proto 这里和大家 分享下
这个我的 nodejs 工作目录,两个 .proto 文件 在 protofile 文件夹中 生成的 net_msg.js 是在 protojs 文件夹中
在这里我么把服务器的整个 流程走一个
1 安装 socket.io
npm install socket.io --save
2 安装 protobufjs
npm install protobufjs --save
3 安装 .proto 编译工具 用于把 .proto 编译成 .js 使用
npm install pbjs
或者
npm install protobufjs -g --save
对照我的项目路径 我的编译命令 就这么写了
- ./protofile/net_msg.proto 是要编译文件相对路径
- ./protoJs/net_msg.js 是生成文件的相对路径
- 其他的照着写就好
pbjs -t static-module ./protofile/net_msg.proto -w commonjs > ./protoJs/net_msg.js
你也可以写个 .bat 工具 一键生成 对应的 js
@echo off
echo pbjs 静态编译 开始
pbjs -t static-module ./protofile/net_msg.proto -w commonjs > ./protoJs/net_msg.js
echo pbjs 静态编译 结束
pause
使用由 .proto生成 的js
const netProto = require('./protobuf/protoJs/net_msg')['netProto']
'./protobuf/protoJs/net_msg' 是 .js 路径 后面中括号 是 .proto 的 'package' 名称 就是包名;
Hearbeat 是 .proto 里面定义的一个‘类’
let heartbeat = new netProto.Heartbeat()
heartbeat.msgType = 9
heartbeat.timeStamp = 666666
console.log("001:", netProto.Heartbeat.encode(heartbeat).finish())//解码
let obj = netProto.Heartbeat.decode( data)//编码
console.log(obj)
console.log(obj.msgType)
console.log(obj.timeStamp)
socket.broadcast.send(netProto.Heartbeat.encode(heartbeat).finish())
服务端完整代码:
//引用 Http 模块
const http = require('http')
//文件读写
const fs = require('fs');
//床架一个WEB服务 socket 基于 Web 服务
const app = http.createServer()
//引用 socket.io 模块
const io = require('socket.io')(app)
const port = 3000
const netProto = require('./protobuf/protoJs/net_msg')['netProto']
app.listen(port, function () {
console.log('服务器启动成功!端口监听:' + port)
});
let onLineConnets = {}
let index = 0
io.on('connect', onConnect);
function onConnect(socket) {
console.log('有机器连接服务器')
socket.name = ++index;
onLineConnets[socket.name] = socket
socket.on('message', function (data) {
console.log("data:", data)
//let obj = messages.heartbeat.decode(data)
// console.log(obj)
// console.log(obj.msg_type)
// console.log(obj.timeStamp)
let heartbeat = new netProto.Heartbeat()
heartbeat.msgType = 9
heartbeat.timeStamp = 666666
//console.log("000:", netProto.Heartbeat.encode(heartbeat))
console.log("001:", netProto.Heartbeat.encode(heartbeat).finish())
let obj = netProto.Heartbeat.decode( data)
console.log(obj)
console.log(obj.msgType)
console.log(obj.timeStamp)
socket.broadcast.send(netProto.Heartbeat.encode(heartbeat).finish())
})
socket.on('disconnect', function () {
console.log('客户端断开连接')
delete onLineConnets[socket.name]
})
socket.on('error', function () {
console.log('客户端发生错误')
delete onLineConnets[socket.name]
})
}
Layaair 客户端中 解析 和 发送需要和 服务器对于上 要不然出问题,
这里面有需要两个文件 一个是 socket.io.d.ts 另一个是 socket.io.js
需要的 index.html 中 引入socket.io.js
socket.io.d.ts 放入Libs中
下载地址
/*
* socket 消息先关; BaseSingleton 单例
*/
class SocketManager extends BaseSingleton {
private socket: SocketIOClient.Socket;//socket.io.d.ts中定义
private serverHost: string;
public socketProxy: MessageBase;//处理协议的中间件
constructor() {
super()
}
public connect(url): void {
if (this.isConnect) {
this.closeConnect();
}
this.serverHost = url
Log.trace("开始连接服务器服务器: " + url);
let self = this;
this.socket = io.connect(url)
this.socketProxy = new MessageProxy(this.socket)
this.socket.on(SocketConst.SOCKET_CONNECT, function () {
self.onSocketConnect()
});
this.socket.on(SocketConst.SOCKET_DISCONNECT, function () {
self.onSocketDisconnect()
})
this.socket.on(SocketConst.SOCKET_ERROR, function () {
self.onConnectError()
})
this.socket.on(SocketConst.SOCKET_MESSAGE, function (message: any) {
self.onSocketMessage(message)
})
}
public get isConnect(): boolean {
if (this.socket != null && this.socket.connected == true) {
return true;
}
else {
return false;
}
}
public get SocketProxy():MessageBase{
return this.socketProxy
}
public closeConnect(): void {
if ( this.isConnect) {
this.socket.close()
}
}
private onSocketConnect(): void {
Application.MessageCenter.dispatch(MessageConst.SOCKET_CONNCETSCUESS);
}
private onSocketDisconnect(): void {
Log.trace("断开连接!");
Application.MessageCenter.dispatch(MessageConst.SOCKET_DISCONNECT);
}
private onConnectError(e: Event = null): void {
Log.trace("连接错误!", e);
Application.MessageCenter.dispatch(MessageConst.SOCKET_CONNCETERROR);
}
private onSocketMessage(message: any) {
this.socketProxy.receive(message);
}
}
这个脚本主要集成了 发送 编码 socket 和 收到socket 解析
/*
* name;
*/
class MessageProxy implements MessageBase {
private socket: SocketIOClient.Socket;
private bufferReceive: Laya.Byte;
private bufferSend: Laya.Byte;
private receiveArray: Uint8Array;
constructor(socket: SocketIOClient.Socket) {
this.socket = socket
this.bufferReceive = new Laya.Byte();
this.bufferSend = new Laya.Byte();
}
public receive(msg: any): void {
//console.log('receive===>', msg)
let base: netProto.IBaseMsg = this.decode(msg)
//把消息广播出去
Application.MessageCenter.dispatch(base.msg_type.toString(), this.receiveArray);
}
public send(msg: any, encode: Function): void {
this.socket.send(this.encode(msg, encode).buffer)
}
public decode(msg: any): any {
this.bufferReceive.clear()
this.bufferReceive.writeArrayBuffer(msg)
console.log("BaseMsg:", this.bufferReceive.buffer)
this.receiveArray = new Uint8Array(this.bufferReceive.buffer)
let base: netProto.IBaseMsg = netProto.BaseMsg.decode(this.receiveArray)
console.log("BaseMsg:", this.bufferReceive.buffer)
return base;
}
public encode(msg: any, encode: Function): any {
this.bufferSend.clear()
this.bufferSend.writeArrayBuffer(encode(msg).finish());
return this.bufferSend;
}
}
大概的使用:
/*
* name;
*/
class SceneMain extends ui.SceneMainUI {
constructor() {
super();
this.init()
}
private init(): void {
//开始连接 socket
SocketManager.getInstance().connect(ConfigSocket.getWsRoot)
//监听sockrt.io 连接成功
Application.MessageCenter.addListener(MessageConst.SOCKET_CONNCETSCUESS, function () {
Log.trace('服务器连接成功')
}, this)
// Application.MessageCenter.addListener(SocketConst.SOCKET_NOCONNECT, function(){
// Log.trace('服务器连接错误-----')
// },this)
//服务器消息
Application.MessageCenter.addListener('9', function (date) {
console.log(date)
let heartbeat1 = netProto.Heartbeat.decode(date)
console.log('heartbeat.timeStamp:', heartbeat1.timeStamp)
let heartbeat = new netProto.Heartbeat()
heartbeat.msg_type = 9
heartbeat.timeStamp = new Date().getTime()
SocketManager.getInstance().SocketProxy.send(heartbeat, netProto.Heartbeat.encode);
}, this)
let heartbeat = new netProto.Heartbeat()
heartbeat.msg_type = 9
heartbeat.timeStamp = new Date().getTime()
SocketManager.getInstance().SocketProxy.send(heartbeat, netProto.Heartbeat.encode);
}
private login() {
}
private randomNum(min, max) {
return parseInt(Math.random() * (max - min + 1) + min, 10);
}
}
来源:CSDN
作者:nicepainkiller
链接:https://blog.csdn.net/nicepainkiller/article/details/91043252