uniapp在APP上如何使用websocket--详解
UniApp 在 APP 端如何使用 WebSocket以及常见问题
一、WebSocket 基础概念
WebSocket 是一种在单个TCP连接上进行全双工通信的协议,适用于实时数据传输场景(如聊天室、实时游戏、股票行情等)。
与传统HTTP对比
特性 | WebSocket | HTTP |
---|---|---|
连接方式 | 长连接 | 短连接 |
通信方向 | 全双工 | 半双工 |
数据格式 | 二进制/文本 | 文本 |
首部大小 | 2-10字节 | 8000+字节 |
二、UniApp 中使用 WebSocket
1. API 概览
UniApp 封装了微信小程序风格的 WebSocket API:
uni.connectSocket()
- 创建连接uni.onSocketOpen()
- 监听连接打开uni.onSocketError()
- 监听错误uni.sendSocketMessage()
- 发送消息uni.onSocketMessage()
- 接收消息uni.closeSocket()
- 关闭连接uni.onSocketClose()
- 监听关闭
2. 完整使用示例
// websocket.js
let socketTask = null;
let reconnectAttempts = 0;
const maxReconnectAttempts = 5;export function connectWebSocket() {return new Promise((resolve, reject) => {const url = 'wss://your-websocket-server.com';// 创建连接socketTask = uni.connectSocket({url: url,success: () => {console.log('WebSocket 连接创建中...');},fail: (err) => {console.error('连接创建失败:', err);reject(err);}});// 监听打开事件socketTask.onOpen((res) => {console.log('WebSocket 连接已打开');reconnectAttempts = 0;resolve(socketTask);});// 监听错误事件socketTask.onError((err) => {console.error('WebSocket 错误:', err);handleReconnection();reject(err);});// 监听关闭事件socketTask.onClose((res) => {console.log('WebSocket 连接已关闭', res);if (!res.code === 1000) { // 非正常关闭handleReconnection();}});});
}function handleReconnection() {if (reconnectAttempts < maxReconnectAttempts) {reconnectAttempts++;const delay = Math.min(1000 * reconnectAttempts, 5000);console.log(`尝试第 ${reconnectAttempts} 次重连,${delay}ms后执行`);setTimeout(() => {connectWebSocket().catch(console.error);}, delay);} else {console.error(`已达到最大重连次数 ${maxReconnectAttempts}`);}
}// 发送消息
export function sendWebSocketMessage(message) {return new Promise((resolve, reject) => {if (!socketTask || socketTask.readyState !== 1) {reject('WebSocket 未连接');return;}socketTask.send({data: JSON.stringify(message),success: () => resolve(),fail: (err) => reject(err)});});
}// 关闭连接
export function closeWebSocket() {if (socketTask) {socketTask.close({code: 1000,reason: '用户主动关闭'});}
}
3. 心跳机制实现
let heartbeatTimer = null;function startHeartbeat() {// 每30秒发送一次心跳heartbeatTimer = setInterval(() => {sendWebSocketMessage({type: 'heartbeat',timestamp: Date.now()}).catch(() => {clearInterval(heartbeatTimer);});}, 30000);
}// 在onOpen中调用
socketTask.onOpen(() => {startHeartbeat();
});// 在onClose中清除
socketTask.onClose(() => {clearInterval(heartbeatTimer);
});
4. 消息队列处理
当网络不稳定时,可实现消息队列:
let messageQueue = [];
let isSending = false;async function processQueue() {if (isSending || messageQueue.length === 0) return;isSending = true;const message = messageQueue.shift();try {await sendWebSocketMessage(message);} catch (err) {messageQueue.unshift(message); // 重新放回队列} finally {isSending = false;processQueue();}
}export function queueMessage(message) {messageQueue.push(message);processQueue();
}
三、注意事项
-
平台差异:
- iOS 对后台WebSocket连接限制严格
- 部分安卓机型可能在锁屏后断开连接
-
安全要求:
- 必须使用
wss
协议(SSL加密) - 建议实现消息加密(如AES)
- 必须使用
-
性能优化:
- 大数据量传输建议使用ArrayBuffer
- 避免频繁发送小消息(可合并发送)
-
调试技巧:
// 开启调试模式 uni.setEnableDebug({enableDebug: true });
四、完整页面示例
<template><view class="container"><button @click="connect">连接WebSocket</button><button @click="send">发送测试消息</button><button @click="close">关闭连接</button><scroll-view scroll-y class="message-box"><view v-for="(msg, index) in messages" :key="index">{{ msg }}</view></scroll-view></view>
</template><script>
import { connectWebSocket, sendWebSocketMessage, closeWebSocket } from '@/utils/websocket';export default {data() {return {messages: [],socketTask: null}},onUnload() {closeWebSocket();},methods: {async connect() {try {this.socketTask = await connectWebSocket();this.socketTask.onMessage((res) => {this.messages.push('收到消息: ' + res.data);});this.messages.push('WebSocket 已连接');} catch (err) {this.messages.push('连接失败: ' + err);}},async send() {try {await sendWebSocketMessage({type: 'test',content: 'Hello WebSocket',timestamp: Date.now()});this.messages.push('消息已发送');} catch (err) {this.messages.push('发送失败: ' + err);}},close() {closeWebSocket();this.messages.push('已主动关闭连接');}}
}
</script><style>
.container {padding: 20px;
}
.message-box {height: 300px;margin-top: 20px;border: 1px solid #eee;padding: 10px;
}
</style>
五、常见问题解决
Q1: 安卓设备连接不稳定
-
解决方案:在manifest.json中配置:
"app-plus": {"keepRunning": true,"optimization": {"keepAlive": true} }
Q2: iOS后台断连
-
解决方案:启用后台模式(需在manifest.json中声明):
"ios": {"UIBackgroundModes": ["audio"] }
并通过心跳保持活跃
Q3: 真机调试无法连接
- 检查项:
- 是否使用HTTPS/WSS
- 域名是否加入白名单
- 手机网络是否正常
Q4: 如何发送二进制数据
// 发送ArrayBuffer
const buffer = new ArrayBuffer(8);
socketTask.send({data: buffer,fail: console.error
});