环境
cocos creator版本:3.8.0
开发语言:ts
操作系统:windows
http部分
直接使用 XMLHttpRequest 创建http请求
// _getHttpUrl 方法自己写字符串拼接
public httpPostJsonRequest(uri: string, headData: any, data: any, cb: Function) {
let xhr: XMLHttpRequest = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState == XMLHttpRequest.DONE) {
if (xhr.status == 200) {// statusText:OK https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/status
let jsonStr: string = xhr.responseText;
console.log('tg post response:', jsonStr);
cb && cb(null, "", jsonStr);
}
}
}
xhr.ontimeout = function (event: ProgressEvent) {
console.log(`http post [${uri}] timeout!`);
cb && cb(event, "Timeout!", "{}");
};
xhr.onerror = (event: ProgressEvent) => {
console.error('XMLHttpRequest error', event);
cb && cb(event, "Request error!", "{}");
}
let url: string = this._getHttpUrl(uri);
xhr.open('POST', url);
xhr.setRequestHeader("Content-type", "application/json");
if (headData) {
for (let k in headData) {
xhr.setRequestHeader(k, headData[k]);
}
}
let json = JSON.stringify(data);
console.log('send http post request:', json);
xhr.send(json);
}
public httpGetRequest(uri: string, headData: any, cb: NetCbFunc) {
let xhr: XMLHttpRequest = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState == XMLHttpRequest.DONE) {
if (xhr.status == 200) {// statusText:OK https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/status
let jsonStr: string = xhr.responseText;
console.log('http get response:', jsonStr);
cb && cb(null, '', jsonStr);
}
}
}
xhr.ontimeout = function (event: ProgressEvent) {
console.log('http get request timeout!');
cb && cb(event, "Timeout!", "{}");
};
xhr.onerror = (event: ProgressEvent) => {
console.error('XMLHttpRequest error');
cb && cb(event, "Request error!", "{}");
}
if (headData) {
for (let k in headData) {
xhr.setRequestHeader(k, headData[k]);
}
}
let url: string = this._getHttpUrl(uri);
xhr.open('GET', url);
console.log('send TG get request:', url);
xhr.send();
}
websocket部分
websocket认证:因为ts的websocket不能修改header,所以在创建websocket的url参数里添加params作为Authorization认证数据,例如 let ws = new WebSocket("localhost/ws?token=xxxx");
protobuf部分
安装环境:
- protobufjs ^7.3.2:安装命令 npm install --save protobufjs
-
protobufjs-cli:用于导出proto文件为js/ts,安装命令 npm i -g protobufjs-cli
不安装 protobufjs-cli 也可以,protobufjs可以直接读取proto文件,为了ts编写方便,做了转换。
转换命令(放在package.json的scripts下就行):
-
"build-proto:pbjs": "pbjs --dependency protobufjs/minimal.js --target static-module --wrap commonjs --out [导出路径]/proto.js [proto文件路径]/*.proto",
-
"build-proto:pbts": "pbts --main --out [导出路径]/proto.d.ts [上一步js导出路径]/*.js"
ts代码引用:import proto from '[js导出路径]/proto.js';
多个proto文件都会编入到一个js里。
websocket + protobuf
let ws: WebSocket = null;
function connectGameServer() {
ws = new WebSocket("localhost/ws?token=xxxx");
ws.binaryType = "arraybuffer";
ws.onopen = (ev: Event) => {}
ws.onmessage = (ev: MessageEvent) => {
// 解析protobuf
onMessage(ev);
}
ws.onerror = (ev: Event) => {}
ws.onclose = (ev: CloseEvent) => {}
}
function sendWebsocketMessage(buffer: Uint8Array) {
if (ws.readyState === WebSocket.OPEN) {
ws.send(buffer);
}
}
// 发送
function sendRequest(msgId, req) {
// 根据msgId获取到proto对应的类 msgClass
const err = msgClass.verify(req);
if (err) {
console.log('sendRequest error:', err);
return;
}
let obj: ProtoMsgClass = msgClass.create(req);
let writer: protobufjs.Writer = msgClass.encode(obj);
// Uint8Array 和 DataView 需要修改工程目录下的tsconfig.json文件,compilerOptions部分,
// "allowSyntheticDefaultImports": true,
// "target": "ES2019",
// "lib": [ "ES2020", "dom" ]
let messageBuffer: Uint8Array = writer.finish();
// 发送的数据格式需要和服务端对齐,这里的是瞎写的,反正组装成 Uint8Array 数据格式就行
let dv = new DataView(new ArrayBuffer(123));
dv.setInt32(0, messageBuffer.length);
dv.setBigUint64(4, BigInt(msgId));
// 网上找到的这个代码,因为vscode的错误提示改成自己写的一个方法了。
// const targetBuffer = Buffer.concat([new Uint8Array(dv.buffer), messageBuffer])
const targetBuffer = BufferConcat(new Uint8Array(dv.buffer), messageBuffer);
this.sendWebsocketMessage(targetBuffer);
}
public static BufferConcat(buf1: Uint8Array, buf2: Uint8Array): Uint8Array {
let buf: Uint8Array = null;
if (buf1 && buf2) {
let len1 = buf1.length;
let len2 = buf2.length;
buf = new Uint8Array(len1 + len2);
buf.set(buf1);
buf.set(buf2, len1);
}
return buf;
}
// 接收
function onMessage(ev: MessageEvent) {
const binary = new Uint8Array(ev.data);
// 解析格式和服务端对齐就行,123、456、789都是瞎写的
const buf = binary.slice(123, 456);
let view = new DataView(buf.buffer, 0);
const msgId = +view.getBigUint64(0, false).toString();
// 根据msgId获取msgClass
if (msgClass) {
const bodyBuf = binary.slice(789);
const msg = msgClass.decode(bodyBuf);
console.log('onMessage', msg);
// 调用对应回调处理消息
} else {
console.log('onMessage no map class', msgId);
}
}
参考:
- websocket进行Authorization验证_websocket authorization-CSDN博客
- 前端在WebSocket中加入Token_websocket添加请求头token-CSDN博客
- javascript - WebSocket connection failed: Error during WebSocket handshake: Unexpected response code: 400 - Stack Overflow
- Essential guide to WebSocket authentication
- 8 best WebSocket libraries for Node
- 在Javascript中将Uint8Array转换为BigInt-腾讯云开发者社区-腾讯云
- websocket创建时附加额外信息 [如自定义headers信息(利用nginx)]_websocket自定义header-CSDN博客
- 前端如何在 WebSocket 的请求头中使用标准 HTTP 头携带 Authorization 信息,添加请求头_websocket添加请求头-CSDN博客
- JS/TS项目中使用websocket与protobuf_ts protobuf-CSDN博客
- TS项目中使用Protobuf的解决方案_protobuf ts-CSDN博客
- cocos creator使用protobuf详细方案 - Creator 3.x - Cocos中文社区
- cocos creator使用protobuf详细方案 - Creator 3.x - Cocos中文社区
- WebSocket 客户端 | Cocos Creator
- cocos-test-projects/assets/cases/network/NetworkCtrl.ts at 07f5671e18ef3ed4494d8cba6c2f9499766467a6 · cocos/cocos-test-projects · GitHub
- CocosCreator中加入webSocket的使用 - Creator 2.x - Cocos中文社区
- Cocos Creator3.8 项目实战(十)使用 protobuf详细教程_cocoscreator protobuf-CSDN博客
- 在cocos creator TS 中如何使用protobuf(自动化,评论中有)_cocoscreator ts 面试-CSDN博客
- cocos creator中webSocket的使用及封装_cocos onfire-CSDN博客
- [CocosCreator]封装WebSocket网络管理器(包含心跳)_cocoscreater socket.io 设置心跳和超时-CSDN博客
- https://zhuanlan.zhihu.com/p/653165384
- https://zhuanlan.zhihu.com/p/616718383
- javascript uint8数组和uint32之间的转换_arcgis unit8转化为unit32-CSDN博客
- node.js - How can I fix compile time errors even using compiler options as target es6 and es2017 in Angular 7? - Stack Overflow
- WebSocket 的请求头(header)中如何携带 authorization
- https://peterolson.github.io/BigInteger.js/BigInteger.min.js
- https://github.com/yume-chan/dataview-bigint-polyfill
- https://github.com/peterolson/BigInteger.js
- CocosCreator与大整数运算库_ts 游戏中大数值怎么计算-CSDN博客
- 【分享】自定义arraybuffer数据结构 - Creator 2.x - Cocos中文社区
- DataView - JavaScript | MDN
- ES6,Number类型和新增的BigInt数据类型,以及数值精度丢失的问题_es6除号-CSDN博客
- CocosCreator 源码./polyfill/array-buffer详解 - 简书
- [ts]typescript高阶之typeof使用_ts typeof-CSDN博客
- TypeScript 【type】关键字的进阶使用方式_typescript type使用-CSDN博客
- 记录JS XMLHttpRequest POST提交JSON数据的格式_xmlrequest post json-CSDN博客
- JS使用XMLHttpRequest对象POST收发JSON格式数据_js发送json-CSDN博客
- https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types