|
@@ -1,225 +1,235 @@
|
|
|
// src/stores/websocket.ts
|
|
|
-import { defineStore } from 'pinia'
|
|
|
-import { $root as protobuf } from '@/common/proto/proto'
|
|
|
-import * as Constant from '@/common/constant/Constant'
|
|
|
-import { useWalletStore } from "@/stores/modules/walletStore"
|
|
|
+import { defineStore } from "pinia";
|
|
|
+import { $root as protobuf } from "@/common/proto/proto";
|
|
|
+import * as Constant from "@/common/constant/Constant";
|
|
|
+import { useWalletStore } from "@/stores/modules/walletStore";
|
|
|
|
|
|
-export const useWebSocketStore = defineStore('webSocketStore', {
|
|
|
+export const useWebSocketStore = defineStore("webSocketStore", {
|
|
|
// 状态定义
|
|
|
state: () => ({
|
|
|
- socket: null ,
|
|
|
- peer: null,
|
|
|
- lockConnection: false,
|
|
|
- reconnectAttempts: 0,
|
|
|
- maxReconnectAttempts: 5,
|
|
|
- reconnectInterval: 3000,
|
|
|
- messages: [] ,
|
|
|
- unreadMessages: [] ,
|
|
|
- lastMessage: null ,
|
|
|
-
|
|
|
+ socket: null, // socket实例
|
|
|
+ peer: null, // peer实例
|
|
|
+ lockConnection: false, // 锁定连接
|
|
|
+ reconnectAttempts: 0, // 重连次数
|
|
|
+ maxReconnectAttempts: 5, // 最大重连次数
|
|
|
+ reconnectInterval: 3000, // 重连间隔
|
|
|
+ messages: [], // 消息列表
|
|
|
+ unreadMessages: [], // 未读消息列表
|
|
|
+ lastMessage: null, // 最后一条消息
|
|
|
+
|
|
|
// 心跳检测配置
|
|
|
heartCheck: {
|
|
|
- timeout: 10000,
|
|
|
- timeoutObj: null ,
|
|
|
- serverTimeoutObj: null,
|
|
|
- num: 3
|
|
|
- }
|
|
|
+ timeout: 10000, // 连接丢失后,多长时间内没有收到服务端的消息,则认为连接已断开
|
|
|
+ timeoutObj: null, // 定时器对象
|
|
|
+ serverTimeoutObj: null, // 服务器定时器对象
|
|
|
+ num: 3, // 重连次数
|
|
|
+ },
|
|
|
}),
|
|
|
|
|
|
// 计算属性
|
|
|
getters: {
|
|
|
isConnected: (state) => state.socket?.readyState === WebSocket.OPEN,
|
|
|
- hasUnreadMessages: (state) => state.unreadMessages.length > 0
|
|
|
+ hasUnreadMessages: (state) => state.unreadMessages.length > 0,
|
|
|
},
|
|
|
|
|
|
// 方法
|
|
|
actions: {
|
|
|
startHeartbeat() {
|
|
|
- const self = this
|
|
|
- const _num = this.heartCheck.num
|
|
|
-
|
|
|
- this.heartCheck.timeoutObj && clearTimeout(this.heartCheck.timeoutObj)
|
|
|
- this.heartCheck.serverTimeoutObj && clearTimeout(this.heartCheck.serverTimeoutObj)
|
|
|
-
|
|
|
+ const self = this;
|
|
|
+ const _num = this.heartCheck.num;
|
|
|
+
|
|
|
+ this.heartCheck.timeoutObj && clearTimeout(this.heartCheck.timeoutObj);
|
|
|
+ this.heartCheck.serverTimeoutObj &&
|
|
|
+ clearTimeout(this.heartCheck.serverTimeoutObj);
|
|
|
+
|
|
|
this.heartCheck.timeoutObj = setTimeout(() => {
|
|
|
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
|
const data = {
|
|
|
type: "heatbeat",
|
|
|
content: "ping",
|
|
|
- }
|
|
|
- const MessageType = protobuf.lookupType("protocol.Message")
|
|
|
- const messagePB = MessageType.create(data)
|
|
|
- const buffer = MessageType.encode(messagePB).finish()
|
|
|
- this.socket.send(buffer)
|
|
|
+ };
|
|
|
+ const MessageType = protobuf.lookupType("protocol.Message");
|
|
|
+ const messagePB = MessageType.create(data);
|
|
|
+ const buffer = MessageType.encode(messagePB).finish();
|
|
|
+ this.socket.send(buffer);
|
|
|
}
|
|
|
|
|
|
self.heartCheck.serverTimeoutObj = setTimeout(() => {
|
|
|
- _num--
|
|
|
+ _num--;
|
|
|
if (_num <= 0) {
|
|
|
- console.log("the ping num is more then 3, close socket!")
|
|
|
- this.socket?.close()
|
|
|
+ console.log("the ping num is more then 3, close socket!");
|
|
|
+ this.socket?.close();
|
|
|
}
|
|
|
- }, self.heartCheck.timeout)
|
|
|
- }, this.heartCheck.timeout)
|
|
|
+ }, self.heartCheck.timeout);
|
|
|
+ }, this.heartCheck.timeout);
|
|
|
},
|
|
|
|
|
|
resetHeartbeat() {
|
|
|
- this.heartCheck.timeoutObj && clearTimeout(this.heartCheck.timeoutObj)
|
|
|
- this.heartCheck.serverTimeoutObj && clearTimeout(this.heartCheck.serverTimeoutObj)
|
|
|
- this.heartCheck.num = 3
|
|
|
+ this.heartCheck.timeoutObj && clearTimeout(this.heartCheck.timeoutObj);
|
|
|
+ this.heartCheck.serverTimeoutObj &&
|
|
|
+ clearTimeout(this.heartCheck.serverTimeoutObj);
|
|
|
+ this.heartCheck.num = 3;
|
|
|
},
|
|
|
|
|
|
connect(userUuid) {
|
|
|
- console.log("开始连接...")
|
|
|
- this.disconnect() // 确保先断开现有连接
|
|
|
-
|
|
|
- this.peer = new RTCPeerConnection()
|
|
|
- this.socket = new WebSocket(`ws://192.168.0.59:8888/api/v1/socket.io?user=${userUuid}`)
|
|
|
+ console.log("开始连接...");
|
|
|
+ this.disconnect(); // 确保先断开现有连接
|
|
|
+
|
|
|
+ this.peer = new RTCPeerConnection();
|
|
|
+ this.socket = new WebSocket(
|
|
|
+ `ws://192.168.0.59:8888/api/v1/socket.io?user=${userUuid}`
|
|
|
+ );
|
|
|
|
|
|
this.socket.onopen = () => {
|
|
|
- this.startHeartbeat()
|
|
|
- console.log("WebSocket连接成功")
|
|
|
- this.webrtcConnection()
|
|
|
- }
|
|
|
+ this.startHeartbeat();
|
|
|
+ console.log("WebSocket连接成功");
|
|
|
+ this.webrtcConnection();
|
|
|
+ };
|
|
|
|
|
|
this.socket.onmessage = (event) => {
|
|
|
- this.startHeartbeat()
|
|
|
- this.handleMessage(event.data)
|
|
|
- }
|
|
|
+ this.startHeartbeat();
|
|
|
+ this.handleMessage(event.data);
|
|
|
+ };
|
|
|
|
|
|
this.socket.onclose = () => {
|
|
|
- console.log("连接关闭,尝试重新连接...")
|
|
|
- this.resetHeartbeat()
|
|
|
- this.reconnect()
|
|
|
- }
|
|
|
+ console.log("连接关闭,尝试重新连接...");
|
|
|
+ this.resetHeartbeat();
|
|
|
+ this.reconnect();
|
|
|
+ };
|
|
|
|
|
|
this.socket.onerror = (error) => {
|
|
|
- console.error("WebSocket错误:", error)
|
|
|
- this.resetHeartbeat()
|
|
|
- this.reconnect()
|
|
|
- }
|
|
|
+ console.error("WebSocket错误:", error);
|
|
|
+ this.resetHeartbeat();
|
|
|
+ this.reconnect();
|
|
|
+ };
|
|
|
},
|
|
|
|
|
|
handleMessage(data) {
|
|
|
- const MessageType = protobuf.lookupType("protocol.Message")
|
|
|
- const reader = new FileReader()
|
|
|
-
|
|
|
+ const MessageType = protobuf.lookupType("protocol.Message");
|
|
|
+ const reader = new FileReader();
|
|
|
+
|
|
|
reader.onload = (event) => {
|
|
|
try {
|
|
|
- const messagePB = MessageType.decode(new Uint8Array(event.target?.result))
|
|
|
+ const messagePB = MessageType.decode(
|
|
|
+ new Uint8Array(event.target?.result)
|
|
|
+ );
|
|
|
const message = MessageType.toObject(messagePB, {
|
|
|
longs: String,
|
|
|
enums: String,
|
|
|
bytes: String,
|
|
|
- })
|
|
|
-
|
|
|
- console.log("收到消息:", message)
|
|
|
-
|
|
|
+ });
|
|
|
+
|
|
|
+ console.log("收到消息:", message);
|
|
|
+
|
|
|
// 更新状态
|
|
|
- this.messages.push(message)
|
|
|
- this.lastMessage = message
|
|
|
-
|
|
|
- if (message.type === "heatbeat") return
|
|
|
-
|
|
|
+ this.messages.push(message);
|
|
|
+ this.lastMessage = message;
|
|
|
+
|
|
|
+ if (message.type === "heatbeat") return;
|
|
|
+
|
|
|
if (message.type === Constant.MESSAGE_TRANS_TYPE) {
|
|
|
- this.dealWebRtcMessage(message)
|
|
|
- return
|
|
|
+ this.dealWebRtcMessage(message);
|
|
|
+ return;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 其他消息处理逻辑...
|
|
|
-
|
|
|
} catch (error) {
|
|
|
- console.error("消息解码错误:", error)
|
|
|
+ console.error("消息解码错误:", error);
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- reader.readAsArrayBuffer(data)
|
|
|
+ };
|
|
|
+
|
|
|
+ reader.readAsArrayBuffer(data);
|
|
|
},
|
|
|
|
|
|
webrtcConnection() {
|
|
|
- if (!this.peer) return
|
|
|
-
|
|
|
+ if (!this.peer) return;
|
|
|
+
|
|
|
this.peer.onicecandidate = (e) => {
|
|
|
if (e.candidate && this.socket) {
|
|
|
const candidate = {
|
|
|
- type: 'answer_ice',
|
|
|
- iceCandidate: e.candidate
|
|
|
- }
|
|
|
+ type: "answer_ice",
|
|
|
+ iceCandidate: e.candidate,
|
|
|
+ };
|
|
|
const message = {
|
|
|
content: JSON.stringify(candidate),
|
|
|
type: Constant.MESSAGE_TRANS_TYPE,
|
|
|
- }
|
|
|
- this.sendMessage(message)
|
|
|
+ };
|
|
|
+ this.sendMessage(message);
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
this.peer.ontrack = (e) => {
|
|
|
if (e && e.streams) {
|
|
|
- const remoteVideo = document.getElementById("remoteVideoReceiver")
|
|
|
- const remoteAudio = document.getElementById("audioPhone")
|
|
|
-
|
|
|
- if (remoteVideo) remoteVideo.srcObject = e.streams[0]
|
|
|
- if (remoteAudio) remoteAudio.srcObject = e.streams[0]
|
|
|
+ const remoteVideo = document.getElementById("remoteVideoReceiver");
|
|
|
+ const remoteAudio = document.getElementById("audioPhone");
|
|
|
+
|
|
|
+ if (remoteVideo) remoteVideo.srcObject = e.streams[0];
|
|
|
+ if (remoteAudio) remoteAudio.srcObject = e.streams[0];
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
},
|
|
|
|
|
|
reconnect() {
|
|
|
- if (this.lockConnection || this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
|
- return
|
|
|
+ if (
|
|
|
+ this.lockConnection ||
|
|
|
+ this.reconnectAttempts >= this.maxReconnectAttempts
|
|
|
+ ) {
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
- this.lockConnection = true
|
|
|
- this.reconnectAttempts++
|
|
|
-
|
|
|
- console.log(`重新连接中... (尝试 ${this.reconnectAttempts}/${this.maxReconnectAttempts})`)
|
|
|
-
|
|
|
+ this.lockConnection = true;
|
|
|
+ this.reconnectAttempts++;
|
|
|
+
|
|
|
+ console.log(
|
|
|
+ `重新连接中... (尝试 ${this.reconnectAttempts}/${this.maxReconnectAttempts})`
|
|
|
+ );
|
|
|
+
|
|
|
setTimeout(() => {
|
|
|
- this.connect(localStorage.uuid)
|
|
|
- this.lockConnection = false
|
|
|
- }, this.reconnectInterval)
|
|
|
+ this.connect(localStorage.uuid);
|
|
|
+ this.lockConnection = false;
|
|
|
+ }, this.reconnectInterval);
|
|
|
},
|
|
|
|
|
|
disconnect() {
|
|
|
if (this.socket) {
|
|
|
- this.resetHeartbeat()
|
|
|
- this.socket.close()
|
|
|
- this.socket = null
|
|
|
+ this.resetHeartbeat();
|
|
|
+ this.socket.close();
|
|
|
+ this.socket = null;
|
|
|
}
|
|
|
if (this.peer) {
|
|
|
- this.peer.close()
|
|
|
- this.peer = null
|
|
|
+ this.peer.close();
|
|
|
+ this.peer = null;
|
|
|
}
|
|
|
- this.reconnectAttempts = 0
|
|
|
+ this.reconnectAttempts = 0;
|
|
|
},
|
|
|
|
|
|
sendMessage(messageData) {
|
|
|
if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
|
|
|
- console.error("WebSocket未连接")
|
|
|
- return false
|
|
|
+ console.error("WebSocket未连接");
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- const walletStore = useWalletStore()
|
|
|
+ const walletStore = useWalletStore();
|
|
|
const data = {
|
|
|
...messageData,
|
|
|
fromUsername: walletStore.username,
|
|
|
from: walletStore.account,
|
|
|
- }
|
|
|
-
|
|
|
+ };
|
|
|
+
|
|
|
try {
|
|
|
- const MessageType = protobuf.lookupType("protocol.Message")
|
|
|
- const messagePB = MessageType.create(data)
|
|
|
- const buffer = MessageType.encode(messagePB).finish()
|
|
|
- this.socket.send(buffer)
|
|
|
- return true
|
|
|
+ const MessageType = protobuf.lookupType("protocol.Message");
|
|
|
+ const messagePB = MessageType.create(data);
|
|
|
+ const buffer = MessageType.encode(messagePB).finish();
|
|
|
+ this.socket.send(buffer);
|
|
|
+ return true;
|
|
|
} catch (error) {
|
|
|
- console.error("消息编码错误:", error)
|
|
|
- return false
|
|
|
+ console.error("消息编码错误:", error);
|
|
|
+ return false;
|
|
|
}
|
|
|
},
|
|
|
|
|
|
dealWebRtcMessage(message) {
|
|
|
// 实现WebRTC消息处理逻辑
|
|
|
- }
|
|
|
- }
|
|
|
-})
|
|
|
+ },
|
|
|
+ },
|
|
|
+});
|