WebSocketSever/assets/Scripts/WebSocketSever.ts
2022-01-19 17:54:26 +08:00

202 lines
7.1 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { ccclass, property } = cc._decorator;
@ccclass
export default class WebSocketSeverClass extends cc.Component {
//#region 外調參數
@property({ type: cc.Label })
public Label: cc.Label = null;
//#endregion
//#region Lifecycle
protected onLoad(): void {
let self: this = this;
// 在原生平台的 Release 模式下或者在 Web/微信小游戏等平台中WebSocketServer 可能没有定义
if (typeof WebSocketServer === "undefined") {
self._addLog("WebSocketServer is not enabled!");
return;
}
switch (cc.sys.getNetworkType()) {
case cc.sys.NetworkType.LAN: {
self._addLog("已連接Wifi");
break;
}
case cc.sys.NetworkType.WWAN: {
self._addLog("未連接Wifi");
break;
}
case cc.sys.NetworkType.NONE: {
self._addLog("未連接Network");
return;
}
default:
break;
}
let ws: any = new WebSocketServer();
ws.onconnection = function (conn: any): any {
self._addLog(`${conn.headers["origin:"]} connect!`);
conn.ondata = function (data: any): any {
self._addLog(`${conn.headers["origin:"]} ondata!`);
self.ParseRpcMessage.bind(self)(data);
self.SendData.bind(self)(ws, "acc", "666");
};
conn.onclose = function (): any {
self._addLog(`${conn.headers["origin:"]} connection gone!`);
};
};
ws.onclose = function (): any {
self._addLog("server is closed!");
};
ws.listen(9005, (err: any): any => {
if (err) {
return;
}
self._addLog("server booted!");
});
}
private _addLog(msg: string): void {
console.log(msg);
this.Label.string += `\n\n${msg}`;
}
public SendData(ws, Method, Data) {
let json = [Method];
if (Data != null && Data != undefined && Data != NaN) {
json[1] = Data;
}
let str = JSON.stringify(json);
if (str.length > 65535) {
this._addLog("要傳的資料太大囉");
throw new Error('要傳的資料太大囉');
}
if (Data != null && Data != undefined && Data != NaN) {
this._addLog(`[RPC] 傳送server資料: ${Method}(${JSON.stringify(Data).replace(/\\/g, "")})`);
} else {
this._addLog(`[RPC] 傳送server資料: ${Method}()`);
}
let strary = this.GetBytes(str);
let buffer = new Uint8Array(4 + strary.byteLength);
let u16ary = new Uint16Array(buffer.buffer, 0, 3);
u16ary[0] = strary.byteLength;
buffer[3] = 0x01;
buffer.set(strary, 4);
ws.send(buffer, (err: any) => {
this._addLog(`${ws.headers["origin:"]} send!`);
//
});
}
public ParseRpcMessage(buffer) {
let startIndex = 0, byteLength = buffer.byteLength;
while (startIndex + 4 < byteLength) {
let strlen = new DataView(buffer, startIndex, 3).getUint16(0, true);
let str = this.GetString(new Uint8Array(buffer, startIndex + 4, strlen));
startIndex += strlen + 4;
try {
let json = JSON.parse(str);
let method = json[0];
let status = json[1][0];
let data = json[1][1];
let resp = {
Method: method,
Status: status,
Data: data,
IsValid: method && status === 0
};
if (data) {
this._addLog(`[RPC] 收到server呼叫:(${resp.Status}): ${resp.Method}(${JSON.stringify(resp.Data)})`);
// ResData(resp.Status, resp.Method, resp.Data);
} else {
this._addLog(`[RPC] 收到server呼叫:(${resp.Status}): ${resp.Method}()`);
// ResData(resp.Status, resp.Method);
}
} catch {
this._addLog(`[RPC] 無法解析Server回應: ${str}`);
throw new Error(`[RPC] 無法解析Server回應: ${str}`);
}
}
}
public GetString(array) {
let str = "";
let i = 0, len = array.length;
while (i < len) {
let c = array[i++];
switch (c >> 4) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
str += String.fromCharCode(c);
break;
case 12: case 13:
str += String.fromCharCode(((c & 0x1F) << 6) | (array[i++] & 0x3F));
break;
case 14:
str += String.fromCharCode(((c & 0x0F) << 12) | ((array[i++] & 0x3F) << 6) | ((array[i++] & 0x3F) << 0));
break;
}
}
return str;
}
public GetBytes(str) {
let len = str.length, resPos = -1;
let resArr = new Uint8Array(len * 3);
for (let point = 0, nextcode = 0, i = 0; i !== len;) {
point = str.charCodeAt(i), i += 1;
if (point >= 0xD800 && point <= 0xDBFF) {
if (i === len) {
resArr[resPos += 1] = 0xef;
resArr[resPos += 1] = 0xbf;
resArr[resPos += 1] = 0xbd;
break;
}
nextcode = str.charCodeAt(i);
if (nextcode >= 0xDC00 && nextcode <= 0xDFFF) {
point = (point - 0xD800) * 0x400 + nextcode - 0xDC00 + 0x10000;
i += 1;
if (point > 0xffff) {
resArr[resPos += 1] = (0x1e << 3) | (point >>> 18);
resArr[resPos += 1] = (0x2 << 6) | ((point >>> 12) & 0x3f);
resArr[resPos += 1] = (0x2 << 6) | ((point >>> 6) & 0x3f);
resArr[resPos += 1] = (0x2 << 6) | (point & 0x3f);
continue;
}
} else {
resArr[resPos += 1] = 0xef;
resArr[resPos += 1] = 0xbf;
resArr[resPos += 1] = 0xbd;
continue;
}
}
if (point <= 0x007f) {
resArr[resPos += 1] = (0x0 << 7) | point;
} else if (point <= 0x07ff) {
resArr[resPos += 1] = (0x6 << 5) | (point >>> 6);
resArr[resPos += 1] = (0x2 << 6) | (point & 0x3f);
} else {
resArr[resPos += 1] = (0xe << 4) | (point >>> 12);
resArr[resPos += 1] = (0x2 << 6) | ((point >>> 6) & 0x3f);
resArr[resPos += 1] = (0x2 << 6) | (point & 0x3f);
}
}
return resArr.subarray(0, resPos + 1);
}
//#endregion
}