参考文章:开发小游戏(服务端开发看)
参考文章《外部域名添加》的开通云服务和添加章节。
参考文章:创建与信息完善
参考文章的第一章。
将域名igo-open-demo.taobao.com配置到后台上,下文会用到;
选择对应的项目,然后选择设置项目保存路径,点击【确定】。
测试服务器(仅做演示用):
wss://igo-open-demo.taobao.com/websocket/test
代码:
const websocketTest = () => { const socketTask = my.connectSocket({ url: 'wss://igo-open-demo.taobao.com/websocket/test', // 开发者服务器接口地址,必须是 wss 协议 multiple: true // 多连接模式,才会返回 SocketTask , success: (res) => { console.log('WebSocket open success', res); }, fail: (err) => { // 如果这里出错了,就要去执行兜底逻辑,比如重新连接 console.error('WebSocket open error', err); } }); socketTask.onOpen(res => { console.log(`WebSocket 已连接,socketTaskID = ${res.data.socketTaskID}`); socketTask.send({ data: 'hi' }); // SocketTask 目前支持多连接。而 my.connectSocket 不支持多连接,所以建议使用SocketTask。 const second = my.connectSocket({ url: 'wss://igo-open-demo.taobao.com/websocket/test', // 开发者服务器接口地址,必须是 wss 协议 multiple: true // 多连接模式,才会返回 SocketTask , success: (res) => { console.log('WebSocket open success', res); }, fail: (err) => { // 如果这里出错了,就要去执行兜底逻辑,比如重新连接 console.error('WebSocket open error', err); } }); second.onOpen(res => { console.log(`WebSocket 已连接,socketTaskID = ${res.data.socketTaskID}`); try { const base64 = utils.arrayBufferToBase64(new Uint8Array([11, 22, 33]).buffer); console.log('base64', base64); second.send({ data: base64, isBuffer: true, // 标记为二进制数据 success: (res) => { console.log('second.send success', res); }, fail: (err) => { console.error('second.send error', err); }, complete: (res) => { console.log('second.send complete', res); } }); } catch (error) { console.log('onOpen Error:', error); } }); second.onMessage((res) => { console.log('second.onMessage 接收到了消息', res.data, res?.data?.isBuffer); try { if (res?.data?.isBuffer) { // 判断是否为二进制数据 const arrayBuffer = utils.base64ToArrayBuffer(res.data?.data); console.log('receive arrayBuffer:', arrayBuffer); my.alert({ content: new Uint8Array(arrayBuffer || []).toString(), title: 'second 收到' }); } } catch (error) { console.error('second onMessage Error:', error); } }); }); socketTask.onClose((res) => { console.log('WebSocket.onClose 连接已关闭!', res); }); socketTask.onError((res) => { console.log('WebSocket.onError 连接失败!', res); }); socketTask.onMessage((res) => { console.log('WebSocket.onMessage 接收到了消息', res.data); }); }
在game.js的代码尾部调用测试函数
websocketTest();
点击构建日志可以查看构建日志
设置权限:设置成员
查看【真机调试】日志
目前淘宝小游戏的http协议不支持二进制数据传输,仅支持字符串发送。所以在例子中将二进制数据转化base64后发送。同时后端发送过来的数据也会被转化成字符串数据,前端也将其解码成二进制数据;注意发送二进制数据要将isBuffer设置为true,在解析的时候判断isBuffer为真则进行二进制转换;
utils.js请查看附录。
二进制转化为base64
const base64 = utils.arrayBufferToBase64(new Uint8Array([11, 22, 33]).buffer); console.log('base64', base64); second.send({ data: base64, isBuffer: true, // 标记为二进制数据 success: (res) => { console.log('second.send success', res); }, fail: (err) => { console.error('second.send error', err); }, complete: (res) => { console.log('second.send complete', res); } });
base64转化为二进制
second.onMessage((res) => { console.log('second.onMessage 接收到了消息', res.data, res?.data?.isBuffer); try { if (res?.data?.isBuffer) { // 判断是否为二进制数据 const arrayBuffer = utils.base64ToArrayBuffer(res.data?.data); console.log('receive arrayBuffer:', arrayBuffer); my.alert({ content: new Uint8Array(arrayBuffer || []).toString(), title: 'second 收到' }); } } catch (error) { console.error('second onMessage Error:', error); } });
部分游戏有建立多个websocket通讯的需求,SocketTask 目前支持多连接,老接口 my.connectSocket 不支持多连接,请注意区别使用。
使用cocos引擎进行websocket通讯,不需要考虑二进制和字符串互转的问题,cocos引擎部分版本支持多连接,请参考下表:
引擎大版本 |
支持版本 |
2.x |
待发布,具体参考cocos的发版说明;若急用请在GitHub下载cocos 2.4.15 的websocket代码; |
3.x |
v3.8.4 |
使用laya引擎进行websocket通讯,不需要考虑二进制和字符串互转的问题,同时laya引擎也支持多连接。
const utils = { /** * @param {Object} target * @param {Object} origin * @param {String} methodName * @param {String} targetMethodName */ cloneMethod (target, origin, methodName, targetMethodName) { if (origin[methodName]) { targetMethodName = targetMethodName || methodName; target[targetMethodName] = origin[methodName].bind(origin); } }, /** * * @param {String} str * @returns */ encode (str) { let encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; const string = String(str); let result = ''; let currentIndex = 0; let sum = void 0; while (string.charAt(0 | currentIndex) || (encodings = '=', currentIndex % 1)) { currentIndex += 0.75; const currentCode = string.charCodeAt(currentIndex); if (currentCode > 255) { // Cannot handle when it is greater than 255 throw new Error('"btoa" failed'); } sum = sum << 8 | currentCode; const encodeIndex = 63 & sum >> 8 - currentIndex % 1 * 8; result += encodings.charAt(encodeIndex); } return result; }, /** * * @param {String} str */ decode (str) { const encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; let res = ''; const string = String(str).replace(/[=]+$/, ''); let o; let r; let i = 0; let currentIndex = 0; while (r = string.charAt(currentIndex)) { currentIndex += 1; r = encodings.indexOf(r); if (~r) { o = i % 4 ? 64 * o + r : r; if (i++ % 4) { res += String.fromCharCode(255 & o >> (-2 * i & 6)); } } } return res; }, /** * * @param {ArrayBuffer} buffer */ arrayBufferToBase64 (buffer) { return utils.encode(utils.arrayBufferToString(buffer)); }, /** * * @param {String} base64 */ base64ToArrayBuffer (base64) { return utils.stringToArrayBuffer(utils.decode(base64)); }, /** * * @param {ArrayBuffer} buffer */ arrayBufferToString (buffer) { let result = ''; const uintArray = new Uint8Array(buffer); const byteLength = uintArray.byteLength; for (let i = 0; i < byteLength; i++) { result += String.fromCharCode(uintArray[i]); } return result; }, /** * * @param {String} string */ stringToArrayBuffer (string) { const length = string.length; const uintArray = new Uint8Array(length); for (let i = 0; i < length; i++) { uintArray[i] = string.charCodeAt(i); } return uintArray.buffer; }, }; module.exports = utils;