binary optimization
This commit is contained in:
		| @@ -87,7 +87,6 @@ export default class DataManager extends Singleton { | |||||||
|         player.direction = { x, y } |         player.direction = { x, y } | ||||||
|         break |         break | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       case InputTypeEnum.WeaponShoot: { |       case InputTypeEnum.WeaponShoot: { | ||||||
|         const { owner, position, direction } = input |         const { owner, position, direction } = input | ||||||
|         const bullet: IBullet = { |         const bullet: IBullet = { | ||||||
|   | |||||||
| @@ -1,7 +1,6 @@ | |||||||
| import Singleton from '../Base/Singleton' | import Singleton from '../Base/Singleton' | ||||||
| import { ApiMsgEnum, IModel, strdecode, strencode } from '../Common'; | import { ApiMsgEnum, IModel, strdecode, strencode } from '../Common'; | ||||||
| import { binaryEncode } from '../Common/Binary'; | import { binaryEncode, binaryDecode } from '../Common/Binary'; | ||||||
| import { binaryDecode } from '../Utils'; |  | ||||||
|  |  | ||||||
| const TIMEOUT = 5000 | const TIMEOUT = 5000 | ||||||
|  |  | ||||||
| @@ -94,8 +93,6 @@ export default class NetworkManager extends Singleton { | |||||||
|  |  | ||||||
|   sendMsg<T extends keyof IModel['msg']>(name: T, data: IModel['msg'][T]) { |   sendMsg<T extends keyof IModel['msg']>(name: T, data: IModel['msg'][T]) { | ||||||
|     const view = binaryEncode(name, data) |     const view = binaryEncode(name, data) | ||||||
|     console.log("view", view.buffer); |  | ||||||
|  |  | ||||||
|     this.ws.send(view.buffer) |     this.ws.send(view.buffer) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -8,80 +8,4 @@ const getNumberWithinString = (str: string) => parseInt(str.match(INDEX_REG)?.[1 | |||||||
| export const sortSpriteFrame = (spriteFrame: Array<SpriteFrame>) => | export const sortSpriteFrame = (spriteFrame: Array<SpriteFrame>) => | ||||||
|   spriteFrame.sort((a, b) => getNumberWithinString(a.name) - getNumberWithinString(b.name)) |   spriteFrame.sort((a, b) => getNumberWithinString(a.name) - getNumberWithinString(b.name)) | ||||||
|  |  | ||||||
| export const rad2Angle = (rad: number) => rad / Math.PI * 180 | export const rad2Angle = (rad: number) => rad / Math.PI * 180 | ||||||
|  |  | ||||||
| export const binaryDecode = (buffer: ArrayBuffer) => { |  | ||||||
|   let index = 0 |  | ||||||
|   const view = new DataView(buffer) |  | ||||||
|   const type = view.getUint8(index++) |  | ||||||
|  |  | ||||||
|   if (type === ApiMsgEnum.MsgClientSync) { |  | ||||||
|     const inputType = view.getUint8(index++) |  | ||||||
|     if (inputType === InputTypeEnum.ActorMove) { |  | ||||||
|       const id = view.getUint8(index++) |  | ||||||
|       const directionX = view.getFloat32(index) |  | ||||||
|       index += 4 |  | ||||||
|       const directionY = view.getFloat32(index) |  | ||||||
|       index += 4 |  | ||||||
|       const dt = view.getFloat32(index) |  | ||||||
|       index += 4 |  | ||||||
|       const msg = { |  | ||||||
|         name: ApiMsgEnum.MsgClientSync, |  | ||||||
|         data: { |  | ||||||
|           type: InputTypeEnum.ActorMove, |  | ||||||
|           id, |  | ||||||
|           direction: { |  | ||||||
|             x: directionX, |  | ||||||
|             y: directionY, |  | ||||||
|           }, |  | ||||||
|           dt |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       return msg |  | ||||||
|     } else if (inputType === InputTypeEnum.WeaponShoot) { |  | ||||||
|       const id = view.getUint8(index++) |  | ||||||
|       const positionX = view.getFloat32(index) |  | ||||||
|       index += 4 |  | ||||||
|       const positionY = view.getFloat32(index) |  | ||||||
|       index += 4 |  | ||||||
|       const directionX = view.getFloat32(index) |  | ||||||
|       index += 4 |  | ||||||
|       const directionY = view.getFloat32(index) |  | ||||||
|       index += 4 |  | ||||||
|       const msg = { |  | ||||||
|         name: ApiMsgEnum.MsgClientSync, |  | ||||||
|         data: { |  | ||||||
|           type: InputTypeEnum.WeaponShoot, |  | ||||||
|           id, |  | ||||||
|           position: { |  | ||||||
|             x: positionX, |  | ||||||
|             y: positionY, |  | ||||||
|           }, |  | ||||||
|           direction: { |  | ||||||
|             x: directionX, |  | ||||||
|             y: directionY, |  | ||||||
|           }, |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       return msg |  | ||||||
|     } else { |  | ||||||
|       const dt = view.getFloat32(index) |  | ||||||
|       index += 4 |  | ||||||
|       const msg = { |  | ||||||
|         name: ApiMsgEnum.MsgClientSync, |  | ||||||
|         data: { |  | ||||||
|           type: InputTypeEnum.TimePast, |  | ||||||
|           dt, |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       return msg |  | ||||||
|     } |  | ||||||
|   } else { |  | ||||||
|     return { |  | ||||||
|       name: type, |  | ||||||
|       data: JSON.parse(strdecode(new Uint8Array(buffer.slice(1)))) |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -1,57 +1,92 @@ | |||||||
| import { ApiMsgEnum, InputTypeEnum } from "./Enum"; | import { ApiMsgEnum, InputTypeEnum } from "./Enum"; | ||||||
| import { strencode } from "./Utils"; | import { strdecode, strencode } from "./Utils"; | ||||||
|  |  | ||||||
|  | const encodeActorMove = (proto: ApiMsgEnum, data: any, view: DataView, index: number) => { | ||||||
|  |   view.setUint8(index++, data.type) | ||||||
|  |   view.setUint8(index++, data.id) | ||||||
|  |   view.setFloat32(index, data.direction.x) | ||||||
|  |   index += 4 | ||||||
|  |   view.setFloat32(index, data.direction.y) | ||||||
|  |   index += 4 | ||||||
|  |   view.setFloat32(index, data.dt) | ||||||
|  |   index += 4 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const encodeWeaponShoot = (proto: ApiMsgEnum, data: any, view: DataView, index: number) => { | ||||||
|  |   view.setUint8(index++, data.type) | ||||||
|  |   view.setUint8(index++, data.owner) | ||||||
|  |   view.setFloat32(index, data.position.x) | ||||||
|  |   index += 4 | ||||||
|  |   view.setFloat32(index, data.position.y) | ||||||
|  |   index += 4 | ||||||
|  |   view.setFloat32(index, data.direction.x) | ||||||
|  |   index += 4 | ||||||
|  |   view.setFloat32(index, data.direction.y) | ||||||
|  |   index += 4 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export const encdoeTimePast = (proto: ApiMsgEnum, data: any, view: DataView, index: number) => { | ||||||
|  |   view.setUint8(index++, data.type) | ||||||
|  |   view.setFloat32(index, data.dt) | ||||||
|  |   index += 4 | ||||||
|  | } | ||||||
|  |  | ||||||
| export const binaryEncode = (proto: ApiMsgEnum, data: any): DataView => { | export const binaryEncode = (proto: ApiMsgEnum, data: any): DataView => { | ||||||
|   if (proto === ApiMsgEnum.MsgClientSync) { |   if (proto === ApiMsgEnum.MsgClientSync) { | ||||||
|     switch (data.type) { |     if (data.type === InputTypeEnum.ActorMove) { | ||||||
|       case InputTypeEnum.ActorMove: { |       let index = 0 | ||||||
|         let index = 0 |       const ab = new ArrayBuffer(3 + 12) | ||||||
|         const ab = new ArrayBuffer(3 + 12) |       const view = new DataView(ab) | ||||||
|         const view = new DataView(ab) |       view.setUint8(index++, proto) | ||||||
|         view.setUint8(index++, proto) |       encodeActorMove(proto, data, view, index) | ||||||
|         view.setUint8(index++, data.type) |       return view | ||||||
|         view.setUint8(index++, data.id) |     } else if (data.type === InputTypeEnum.WeaponShoot) { | ||||||
|         view.setFloat32(index, data.direction.x) |       let index = 0 | ||||||
|         index += 4 |       const ab = new ArrayBuffer(3 + 16) | ||||||
|         view.setFloat32(index, data.direction.y) |       const view = new DataView(ab) | ||||||
|         index += 4 |       view.setUint8(index++, proto) | ||||||
|         view.setFloat32(index, data.dt) |       encodeWeaponShoot(proto, data, view, index) | ||||||
|         index += 4 |       return view | ||||||
|         return view |     } else { | ||||||
|       } |       let index = 0 | ||||||
|       case InputTypeEnum.WeaponShoot: { |       const ab = new ArrayBuffer(2 + 4) | ||||||
|         let index = 0 |       const view = new DataView(ab) | ||||||
|         const ab = new ArrayBuffer(3 + 16) |       view.setUint8(index++, proto) | ||||||
|         const view = new DataView(ab) |       encdoeTimePast(proto, data, view, index) | ||||||
|         view.setUint8(index++, proto) |       return view | ||||||
|         view.setUint8(index++, data.type) |     } | ||||||
|         view.setUint8(index++, data.id) |   } else if (proto === ApiMsgEnum.MsgServerSync) { | ||||||
|         view.setFloat32(index, data.position.x) |     let total = 0 | ||||||
|         index += 4 |     for (let i = 0; i < data.length; i++) { | ||||||
|         view.setFloat32(index, data.position.y) |       const item = data[i]; | ||||||
|         index += 4 |       if (item.type === InputTypeEnum.ActorMove) { | ||||||
|         view.setFloat32(index, data.direction.x) |         total += 14 | ||||||
|         index += 4 |       } else if (item.type === InputTypeEnum.WeaponShoot) { | ||||||
|         view.setFloat32(index, data.direction.y) |         total += 18 | ||||||
|         index += 4 |       } else { | ||||||
|         return view |         total += 5 | ||||||
|       } |  | ||||||
|       case InputTypeEnum.TimePast: { |  | ||||||
|         let index = 0 |  | ||||||
|         const ab = new ArrayBuffer(1 + 1 + 4) |  | ||||||
|         const view = new DataView(ab) |  | ||||||
|         view.setUint8(index++, proto) |  | ||||||
|         view.setUint8(index++, data.type) |  | ||||||
|         view.setFloat32(index, data.dt) |  | ||||||
|         index += 4 |  | ||||||
|         return view |  | ||||||
|       } |  | ||||||
|       default: { |  | ||||||
|         const ab = new ArrayBuffer(0) |  | ||||||
|         const view = new DataView(ab) |  | ||||||
|         return view |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |     const ab = new ArrayBuffer(1 + 1 + total) | ||||||
|  |     const view = new DataView(ab) | ||||||
|  |     let index = 0 | ||||||
|  |     view.setUint8(index++, proto) | ||||||
|  |     view.setUint8(index++, data.length) | ||||||
|  |     for (let i = 0; i < data.length; i++) { | ||||||
|  |       const item = data[i]; | ||||||
|  |       if (item.type === InputTypeEnum.ActorMove) { | ||||||
|  |         encodeActorMove(proto, item, view, index) | ||||||
|  |         index += 14 | ||||||
|  |       } else if (item.type === InputTypeEnum.WeaponShoot) { | ||||||
|  |         encodeWeaponShoot(proto, item, view, index) | ||||||
|  |         index += 18 | ||||||
|  |       } else { | ||||||
|  |         encdoeTimePast(proto, item, view, index) | ||||||
|  |         index += 5 | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return view | ||||||
|   } else { |   } else { | ||||||
|     let index = 0 |     let index = 0 | ||||||
|     const str = JSON.stringify(data) |     const str = JSON.stringify(data) | ||||||
| @@ -64,4 +99,113 @@ export const binaryEncode = (proto: ApiMsgEnum, data: any): DataView => { | |||||||
|     } |     } | ||||||
|     return view |     return view | ||||||
|   } |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const decodeActorMove = (view: DataView, index: number) => { | ||||||
|  |   const id = view.getUint8(index++) | ||||||
|  |   const directionX = view.getFloat32(index) | ||||||
|  |   index += 4 | ||||||
|  |   const directionY = view.getFloat32(index) | ||||||
|  |   index += 4 | ||||||
|  |   const dt = view.getFloat32(index) | ||||||
|  |   index += 4 | ||||||
|  |   const msg = { | ||||||
|  |     name: ApiMsgEnum.MsgClientSync, | ||||||
|  |     data: { | ||||||
|  |       type: InputTypeEnum.ActorMove, | ||||||
|  |       id, | ||||||
|  |       direction: { | ||||||
|  |         x: directionX, | ||||||
|  |         y: directionY, | ||||||
|  |       }, | ||||||
|  |       dt | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return msg | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const decodeWeaponShoot = (view: DataView, index: number) => { | ||||||
|  |   const owner = view.getUint8(index++) | ||||||
|  |   const positionX = view.getFloat32(index) | ||||||
|  |   index += 4 | ||||||
|  |   const positionY = view.getFloat32(index) | ||||||
|  |   index += 4 | ||||||
|  |   const directionX = view.getFloat32(index) | ||||||
|  |   index += 4 | ||||||
|  |   const directionY = view.getFloat32(index) | ||||||
|  |   index += 4 | ||||||
|  |   const msg = { | ||||||
|  |     name: ApiMsgEnum.MsgClientSync, | ||||||
|  |     data: { | ||||||
|  |       type: InputTypeEnum.WeaponShoot, | ||||||
|  |       owner, | ||||||
|  |       position: { | ||||||
|  |         x: positionX, | ||||||
|  |         y: positionY, | ||||||
|  |       }, | ||||||
|  |       direction: { | ||||||
|  |         x: directionX, | ||||||
|  |         y: directionY, | ||||||
|  |       }, | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return msg | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const decodeTimePast = (view: DataView, index: number) => { | ||||||
|  |   const dt = view.getFloat32(index) | ||||||
|  |   index += 4 | ||||||
|  |   const msg = { | ||||||
|  |     name: ApiMsgEnum.MsgClientSync, | ||||||
|  |     data: { | ||||||
|  |       type: InputTypeEnum.TimePast, | ||||||
|  |       dt, | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return msg | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export const binaryDecode = (buffer: ArrayBuffer) => { | ||||||
|  |   let index = 0 | ||||||
|  |   const view = new DataView(buffer) | ||||||
|  |   const proto = view.getUint8(index++) | ||||||
|  |  | ||||||
|  |   if (proto === ApiMsgEnum.MsgClientSync) { | ||||||
|  |     const inputType = view.getUint8(index++) | ||||||
|  |     if (inputType === InputTypeEnum.ActorMove) { | ||||||
|  |       return decodeActorMove(view, index) | ||||||
|  |     } else if (inputType === InputTypeEnum.WeaponShoot) { | ||||||
|  |       return decodeWeaponShoot(view, index) | ||||||
|  |     } else { | ||||||
|  |       return decodeTimePast(view, index) | ||||||
|  |     } | ||||||
|  |   } else if (proto === ApiMsgEnum.MsgServerSync) { | ||||||
|  |     const len = view.getUint8(index++) | ||||||
|  |     const res = [] | ||||||
|  |     for (let i = 0; i < len; i++) { | ||||||
|  |       const inputType = view.getUint8(index++) | ||||||
|  |  | ||||||
|  |       if (inputType === InputTypeEnum.ActorMove) { | ||||||
|  |         res.push(decodeActorMove(view, index).data) | ||||||
|  |         index += 13 | ||||||
|  |       } else if (inputType === InputTypeEnum.WeaponShoot) { | ||||||
|  |         res.push(decodeWeaponShoot(view, index).data) | ||||||
|  |         index += 17 | ||||||
|  |       } else { | ||||||
|  |         res.push(decodeTimePast(view, index).data) | ||||||
|  |         index += 4 | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     return { | ||||||
|  |       name: ApiMsgEnum.MsgServerSync, | ||||||
|  |       data: res | ||||||
|  |     } | ||||||
|  |   } else { | ||||||
|  |     return { | ||||||
|  |       name: proto, | ||||||
|  |       data: JSON.parse(strdecode(new Uint8Array(buffer.slice(1)))) | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
| @@ -7,6 +7,7 @@ export * from './Enum' | |||||||
| export * from './Model' | export * from './Model' | ||||||
| export * from './State' | export * from './State' | ||||||
| export * from './Utils' | export * from './Utils' | ||||||
|  | export * from './Binary' | ||||||
|  |  | ||||||
| export interface IModel { | export interface IModel { | ||||||
|   api: { |   api: { | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| import WebSocket from 'ws'; | import WebSocket from 'ws'; | ||||||
| import { EventEmitter } from 'stream'; | import { EventEmitter } from 'stream'; | ||||||
| import { MyServer } from './MyServer'; | import { MyServer } from './MyServer'; | ||||||
| import { binaryDecode, getTime } from '../Utils'; | import { getTime, toArrayBuffer } from '../Utils'; | ||||||
| import { ApiMsgEnum, IModel } from '../Common'; | import { ApiMsgEnum, IModel } from '../Common'; | ||||||
| import { binaryEncode } from '../Common/Binary'; | import { binaryEncode, binaryDecode } from '../Common/Binary'; | ||||||
|  |  | ||||||
| export enum ConnectionEventEnum { | export enum ConnectionEventEnum { | ||||||
|   Close = 'Close', |   Close = 'Close', | ||||||
| @@ -27,7 +27,7 @@ export class Connection extends EventEmitter { | |||||||
|     this.ws.on('message', (buffer: Buffer) => { |     this.ws.on('message', (buffer: Buffer) => { | ||||||
|       // const str = buffer.toString() |       // const str = buffer.toString() | ||||||
|       try { |       try { | ||||||
|         const json = binaryDecode(buffer) |         const json = binaryDecode(toArrayBuffer(buffer)) | ||||||
|         const { name, data } = json |         const { name, data } = json | ||||||
|         // console.log(`${getTime()}接收|字节数${buffer.length}|${this.playerId || -1}|${str}`) |         // console.log(`${getTime()}接收|字节数${buffer.length}|${this.playerId || -1}|${str}`) | ||||||
|         console.log(`${getTime()}接收|字节数${buffer.length}|${this.playerId || -1}|${JSON.stringify(json)}`) |         console.log(`${getTime()}接收|字节数${buffer.length}|${this.playerId || -1}|${JSON.stringify(json)}`) | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| import fs from 'fs-extra' | import fs from 'fs-extra' | ||||||
| import path from 'path' | import path from 'path' | ||||||
| import { ApiMsgEnum, InputTypeEnum, strdecode } from '../Common' |  | ||||||
|  |  | ||||||
| export const getTime = () => new Date().toLocaleString().split("├")[0] | export const getTime = () => new Date().toLocaleString().split("├")[0] | ||||||
|  |  | ||||||
| @@ -37,77 +36,11 @@ export const copyCommon = async () => { | |||||||
|   console.log('同步成功!') |   console.log('同步成功!') | ||||||
| } | } | ||||||
|  |  | ||||||
| export const binaryDecode = (buffer: Buffer) => { | export const toArrayBuffer = (buffer: Buffer) => { | ||||||
|   let index = 0 |   var ab = new ArrayBuffer(buffer.length); | ||||||
|   const type = buffer.readUint8(index++) |   var view = new Uint8Array(ab); | ||||||
|  |   for (var i = 0; i < buffer.length; ++i) { | ||||||
|   if (type === ApiMsgEnum.MsgClientSync) { |     view[i] = buffer[i]; | ||||||
|     const inputType = buffer.readUint8(index++) |  | ||||||
|     if (inputType === InputTypeEnum.ActorMove) { |  | ||||||
|       const id = buffer.readUint8(index++) |  | ||||||
|       const directionX = buffer.readFloatBE(index) |  | ||||||
|       index += 4 |  | ||||||
|       const directionY = buffer.readFloatBE(index) |  | ||||||
|       index += 4 |  | ||||||
|       const dt = buffer.readFloatBE(index) |  | ||||||
|       index += 4 |  | ||||||
|       const msg = { |  | ||||||
|         name: ApiMsgEnum.MsgClientSync, |  | ||||||
|         data: { |  | ||||||
|           type: InputTypeEnum.ActorMove, |  | ||||||
|           id, |  | ||||||
|           direction: { |  | ||||||
|             x: directionX, |  | ||||||
|             y: directionY, |  | ||||||
|           }, |  | ||||||
|           dt |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       return msg |  | ||||||
|     } else if (inputType === InputTypeEnum.WeaponShoot) { |  | ||||||
|       const id = buffer.readUint8(index++) |  | ||||||
|       const positionX = buffer.readFloatBE(index) |  | ||||||
|       index += 4 |  | ||||||
|       const positionY = buffer.readFloatBE(index) |  | ||||||
|       index += 4 |  | ||||||
|       const directionX = buffer.readFloatBE(index) |  | ||||||
|       index += 4 |  | ||||||
|       const directionY = buffer.readFloatBE(index) |  | ||||||
|       index += 4 |  | ||||||
|       const msg = { |  | ||||||
|         name: ApiMsgEnum.MsgClientSync, |  | ||||||
|         data: { |  | ||||||
|           type: InputTypeEnum.WeaponShoot, |  | ||||||
|           id, |  | ||||||
|           position: { |  | ||||||
|             x: positionX, |  | ||||||
|             y: positionY, |  | ||||||
|           }, |  | ||||||
|           direction: { |  | ||||||
|             x: directionX, |  | ||||||
|             y: directionY, |  | ||||||
|           }, |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       return msg |  | ||||||
|     } else { |  | ||||||
|       const dt = buffer.readFloatBE(index) |  | ||||||
|       index += 4 |  | ||||||
|       const msg = { |  | ||||||
|         name: ApiMsgEnum.MsgClientSync, |  | ||||||
|         data: { |  | ||||||
|           type: InputTypeEnum.TimePast, |  | ||||||
|           dt, |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       return msg |  | ||||||
|     } |  | ||||||
|   } else { |  | ||||||
|     return { |  | ||||||
|       name: type, |  | ||||||
|       data: JSON.parse(strdecode(new Uint8Array(buffer.slice(1)))) |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|  |   return ab; | ||||||
| } | } | ||||||
							
								
								
									
										34
									
								
								test.js
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								test.js
									
									
									
									
									
								
							| @@ -1,30 +1,4 @@ | |||||||
| const msg = JSON.stringify({ | const ab = new ArrayBuffer(10) | ||||||
|   a: 123, | const view = new DataView(ab) | ||||||
|   b: true, | view.setFloat32(0, 0.0023) | ||||||
|   c: "456" | console.log(view); | ||||||
| }) |  | ||||||
|  |  | ||||||
| const strencode = (str) => { |  | ||||||
|   let byteArray = []; |  | ||||||
|   for (let i = 0; i < str.length; i++) { |  | ||||||
|     let charCode = str.charCodeAt(i); |  | ||||||
|     if (charCode <= 0x7f) { |  | ||||||
|       byteArray.push(charCode); |  | ||||||
|     } else if (charCode <= 0x7ff) { |  | ||||||
|       byteArray.push(0xc0 | (charCode >> 6), 0x80 | (charCode & 0x3f)); |  | ||||||
|     } else if (charCode <= 0xffff) { |  | ||||||
|       byteArray.push(0xe0 | (charCode >> 12), 0x80 | ((charCode & 0xfc0) >> 6), 0x80 | (charCode & 0x3f)); |  | ||||||
|     } else { |  | ||||||
|       byteArray.push(0xf0 | (charCode >> 18), 0x80 | ((charCode & 0x3f000) >> 12), 0x80 | ((charCode & 0xfc0) >> 6), 0x80 | (charCode & 0x3f)); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return byteArray; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| var arr = strencode(msg) |  | ||||||
| var buffer = Buffer.from(msg) |  | ||||||
|  |  | ||||||
| console.log(buffer) |  | ||||||
| for (let i = 0; i < arr.length; i++) { |  | ||||||
|   console.log(buffer[i], arr[i]); |  | ||||||
| } |  | ||||||
		Reference in New Issue
	
	Block a user