// NetWebSocket.js
const msgpack = require("msgpack-lite");
var NetWebSocket = cc.Class({
extends: cc.Component,
properties: {
wServersURL: null, //连接的服务器地址
wSocket: null,
netType: null
},
statics: {
createWebSocket:function(_netType) {
var self = new NetWebSocket();
self.netType = _netType;
return self;
}
},
connectServer:function(wUrl) {
this.wServersURL = wUrl;
this.wSocket = new WebSocket(wUrl); // "ws://192.168.8.110:1234"
// 为这个 WebSocket 对象制定对应的回调函数
this.wSocket.onopen = this.onopen.bind(this);
this.wSocket.onmessage = this.onmessage.bind(this);
this.wSocket.onclose = this.onclose.bind(this);
this.wSocket.onerror = this.onerror.bind(this);
},
onopen:function(evt){
console.log("连接服务器成功");
},
onclose:function(evt){
console.log("与服务器断开");
this.close();
},
onerror:function(evt){
console.log("连接服务器失败");
this.close();
},
close:function() {
if (this.wSocket) {
this.wSocket.close();
}
this.wSocket = null;
},
isConnectServer:function(){
//readyState属性返回实例对象的当前状态,共有四种。
//CONNECTING:值为0,表示正在连接。
//OPEN:值为1,表示连接成功,可以通信了。
//CLOSING:值为2,表示连接正在关闭。
//CLOSED:值为3,表示连接已经关闭,或者打开连接失败
if (!this.wSocket) { return false; }
if (this.wSocket.readyState !== WebSocket.OPEN) { return false; }
return true;
},
//接收服务器数据
onmessage:function(evt) {
if (evt.data instanceof ArrayBuffer !== true) {
console.error("msg type is wrong: " + typeof evt.data);
return;
}
let array = new Uint8Array(evt.data);
if (array instanceof Uint8Array !== true) {
console.error("msg context type is wrong: " + typeof evt.data);
return;
}
let msgUint8 = this.analysis(array);
const backMsg = msgpack.decode(msgUint8);
if (typeof backMsg !== "object") {
console.error("backMsg decode type is wrong: " + typeof backMsg);
return;
}
console.log("正常接收数据:" + JSON.stringify(backMsg));
},
analysis: function(tmpUint8) {
if(!tmpUint8) { //解析对象为空
return;
}
if(tmpUint8.length < 12) { //头信息长度不够
return;
}
let n0 = tmpUint8[0];
let n1 = tmpUint8[1];
let n2 = n0 + 256*n2 + 12;
if (n2 > tmpUint8.length) { //数据长度不够
return;
}
let msgUint8 = tmpUint8.slice(12, n2);//正常解析
return msgUint8;
},
//发送数据
sendData:function(data){
console.log("发送数据:" + JSON.stringify(data));
const buffer = msgpack.encode(data);
let msgLength = buffer.length;
let len = this.jsToCByShort(msgLength);
let curTime = parseInt(Date.now() / 1000);
let time = this.jsToCByInt(curTime);
let msgId = this.jsToCByInt(data.msgId * ((curTime % 10000) + 1));
let checksum = this.getCheckSum(time + msgId, msgLength, buffer);
let msgToSend = len + checksum + time + msgId;
let msg = this.stringToUint8Array(msgToSend);
let array1 = Array.prototype.slice.call(msg);
let array2 = Array.prototype.slice.call(buffer);
let array = array1.concat(array2);
let msg_ = new Uint8Array(array);
this.wSocket.send(msg);
},
jsToCByShort:function(value) {
return String.fromCharCode(value % 256) + String.fromCharCode(Math.floor(value / 256));
},
jsToCByInt:function(value) {
const lowByte1 = String.fromCharCode(Math.floor(value / (256 * 256 * 256)));
const lowByte2 = String.fromCharCode(Math.floor(value / (256 * 256)) % 256);
const lowByte3 = String.fromCharCode(Math.floor(value / 256) % 256);
const lowByte4 = String.fromCharCode(value % 256);
return lowByte4 + lowByte3 + lowByte2 + lowByte1;
},
getCheckSum:function(time, msglength, msgPackData) {
let crc = "";
let len = time.length + msglength;
if (len < 8) {
crc = this.CRC(time + msgPackData, len);
} else {
crc = this.CRC(time + msgPackData, 8);
}
return this.jsToCByShort(crc);
},
CRC:function(data, length) {
let sum = 65535;
for (let i = 0; i < length; i++) {
let d = data[i].charCodeAt();
sum = this.ByteCRC(sum, d);
}
return sum;
},
ByteCRC:function(sum, data) {
sum = sum ^ data;
for (let i = 0; i < 3; i++) {
if (sum & 1 === 0) {
sum = sum / 2;
} else {
sum = (sum / 2) ^ 0x70B1;
}
}
return sum;
},
stringToUint8Array:function(str) {
let arr = [];
for (let i = 0, j = str.length; i < j; i++) {
arr.push(str.charCodeAt(i));
}
let tmpUint8Array = new Uint8Array(arr);
return tmpUint8Array;
},
});
module.exports = NetWebSocket;
msgpack-lite 添加方式: https://blog.csdn.net/themagickeyjianan/article/details/90711087