当前开发者大部分都是使用的protobubffer那套方案来做前后端的数据交流通信了,这个自定义的arraybuffer方案,是以前做app的时候写的,思路整理了一下,可以看看
ByteArray.ts
export class ByteArray {
endian: boolean;
bytesBuff: any;
bytesBuffView: DataView;
fmt: any;
data: any;
position: any;
length: any;
/**
* @param bytesBuff 请求解码的数据
* @param endian 字节序
*/
constructor(bytesBuff = null, endian = false) {
this.bytesBuff = bytesBuff;
this.bytesBuffView = null;
if (bytesBuff) {
this.bytesBuffView = new DataView(this.bytesBuff);
} else {
this.fmt = [];
this.data = [];
}
this.endian = endian;
this.position = 0;
this.length = 0;
}
destory() {
this.bytesBuff = null;
this.fmt = null;
this.data = null;
this.bytesBuff = null;
this.bytesBuffView = null;
}
readByte() {
var va1 = this.bytesBuffView.getInt8(this.position);
this.position += 1;
return va1;
}
writeByte(b) {
this.fmt.push('b');
this.data.push(b);
this.length += 1;
}
readShort() {
var val = this.bytesBuffView.getInt16(this.position, this.endian);
this.position += 2;
return val;
}
writeShort(h) {
this.fmt.push('h');
this.data.push(h);
this.length += 2;
}
readLong() {
var val = this.bytesBuffView.getBigUint64(this.position, this.endian);
this.position += 8;
return val;
}
writeLong(d) {
this.fmt.push("l");
this.data.push(d);
this.length += 8;
}
readInt() {
var val = this.bytesBuffView.getInt32(this.position, this.endian);
this.position += 4;
return val;
}
writeInt(i) {
this.fmt.push('i');
this.data.push(i);
this.length += 4;
}
readDouble() {
var val = this.bytesBuffView.getFloat64(this.position, this.endian);
this.position += 8;
return val;
}
writeDouble(d) {
this.fmt.push('d');
this.data.push(d);
this.length += 8;
}
readString() {
var l = this.readShort();
if (l < 1) return '';
var u8Arr = new Uint8Array(this.bytesBuff, this.position);
var arr = [];
for (var i = 0; i < l; i++) {
arr[i] = u8Arr[i];
}
var ret = decode(arr);
this.position += l;
return ret;
}
writeString(s) {
var arr = encode(s);
this.writeShort(arr.length);
this.fmt.push('s');
this.data.push(this._uintCharArrToString(arr));
this.length += arr.length;
}
writeMultiByte(str) {
var len = str.length;
for (var i = 0; i < len; i++) {
this.writeByte(str.charCodeAt(i));
}
this.length += len;
}
_uintCharArrToString(arr) {
var ret = '';
for (var i = 0; i < arr.length; i++) {
ret += String.fromCharCode(arr[i]);
}
return ret;
}
getbytes() {
if (this.bytesBuff) {
return this.bytesBuff;
} else {
var buff = new ArrayBuffer(this.length);
var buffView = new DataView(buff);
var len = this.fmt.length;
var dataType = '';
var elm: any = 0;
var index = 0;
for (var i = 0; i < len; i++) {
dataType = this.fmt[i];
elm = this.data[i];
if (dataType == 'b') {
buffView.setInt8(index, elm);
index += 1;
} else if (dataType == 'h') {
buffView.setInt16(index, elm, this.endian);
index += 2;
} else if (dataType == 'i') {
buffView.setInt32(index, elm, this.endian);
index += 4;
} else if (dataType == 'd') {
buffView.setFloat64(index, elm, this.endian);
index += 8;
} else if (dataType == "l") {
buffView.setBigUint64(index, elm, this.endian);
index += 8;
} else if (dataType == 's') {
index += this._fillArryBuffWithString(elm, buff, index);
}
}
return buff;
}
}
_fillArryBuffWithString(strdata, arryBuff, offset) {
if (!strdata) {
return;
}
var len = strdata.length;
var tempdataView = new DataView(arryBuff, offset);
for (var i = 0; i < len; i++) {
tempdataView.setUint8(i, strdata.charCodeAt(i));
}
return len;
}
}
function decode(dotNetBytes) {
var result = “”;
var i = 0;
var c = 0;
var c1 = 0;
var c2 = 0;
var c3 = 0;
if (dotNetBytes.length >= 3) {
if ((dotNetBytes[0] & 0xef) == 0xef
&& (dotNetBytes[1] & 0xbb) == 0xbb
&& (dotNetBytes[2] & 0xbf) == 0xbf) {
i = 3;
}
}
while (i < dotNetBytes.length) {
c = dotNetBytes[i] & 0xff;
if (c < 128) {
result += String.fromCharCode(c);
i++;
}
else if ((c > 191) && (c < 224)) {
if (i + 1 >= dotNetBytes.length)
throw "Un-expected encoding error, UTF-8 stream truncated, or incorrect";
c2 = dotNetBytes[i + 1] & 0xff;
result += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
if (i + 2 >= dotNetBytes.length || i + 1 >= dotNetBytes.length)
throw "Un-expected encoding error, UTF-8 stream truncated, or incorrect";
c2 = dotNetBytes[i + 1] & 0xff;
c3 = dotNetBytes[i + 2] & 0xff;
result += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return result;
}
function encode(stringToEncode, insertBOM = false) {
stringToEncode = stringToEncode.replace(/\r\n/g, “\n”);
var utftext = [];
if (insertBOM == true) {
utftext[0] = 0xef;
utftext[1] = 0xbb;
utftext[2] = 0xbf;
}
for (var n = 0; n < stringToEncode.length; n++) {
var c = stringToEncode.charCodeAt(n);
if (c < 128) {
utftext[utftext.length] = c;
}
else if ((c > 127) && (c < 2048)) {
utftext[utftext.length] = (c >> 6) | 192;
utftext[utftext.length] = (c & 63) | 128;
}
else {
utftext[utftext.length] = (c >> 12) | 224;
utftext[utftext.length] = ((c >> 6) & 63) | 128;
utftext[utftext.length] = (c & 63) | 128;
}
}
return utftext;
}
协议数据结构需要自定义,与后端商定,自定义协议数据结构
import { ByteArray } from “…/interface/ByteArray”;
export enum CMDID {
CTS_LOGIN_REQ = 1002,
STC_LOGIN_RES = 1003,
}
//协议消息头,占20数组长度
export class MESSAGE_HEAD extends ByteArray {
encode(MsgLen, MsgID, zlibFlag, MsgVer, MsgExtension, UserID, sequenceType, sequenceNo) {
this.writeInt(MsgLen);
this.writeInt(MsgID);
this.writeByte(zlibFlag);
this.writeByte(MsgVer);
this.writeByte(MsgExtension);
this.writeInt(UserID);
this.writeByte(sequenceType);
this.writeInt(sequenceNo);
return this.getbytes();
}
decode() {
let msg: any = {};
msg.MsgLen = this.readInt();
msg.MsgID = this.readInt();
msg.zlibFlag = this.readByte();
msg.MsgVer = this.readByte();
msg.MsgExtension = this.readByte();
msg.UserID = this.readInt();
msg.sequenceType = this.readByte();
msg.sequenceNo = this.readInt();
return msg;
}
}
export class CTS_LOGIN_REQ extends ByteArray {
encode(str) {
let msg: any = {};
msg.info = this.writeString(str);
return this.getbytes();
}
decode() {
let msg: any = {};
msg.info = this.readString();
return msg;
}
}
export class STC_LOGIN_RES extends ByteArray {
encode(str) {
let msg: any = {};
msg.info = this.writeString(str);
return this.getbytes();
}
decode() {
let msg: any = {};
msg.info = this.readString();
return msg;
}
}