webSocketStore.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // src/stores/websocket.ts
  2. import { defineStore } from 'pinia'
  3. import { ref } from 'vue'
  4. import { $root as protobuf } from '@/common/proto/proto'
  5. import * as Constant from '@/common/constant/Constant'
  6. // MessageType = $root.lookupType("protocol.Message");
  7. export const useWebSocketStore = defineStore('webSocketStore', () => {
  8. const socket = ref(null) // 创建WebSocket对象
  9. const peer = ref(null) // 创建RTCPeerConnection对象
  10. const lockConnection = ref(false)
  11. const reconnectAttempts = ref(0)
  12. const maxReconnectAttempts = 5
  13. const reconnectInterval = 3000
  14. // 心跳检测
  15. const heartCheck = {
  16. timeout: 10000,
  17. timeoutObj: null,
  18. serverTimeoutObj: null,
  19. num: 3,
  20. start: function () {
  21. const self = this
  22. const _num = this.num
  23. this.timeoutObj && clearTimeout(this.timeoutObj)
  24. this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj)
  25. this.timeoutObj = setTimeout(() => {
  26. if (socket.value?.readyState === 1) {
  27. const data = {
  28. type: "heatbeat",
  29. content: "ping",
  30. }
  31. const message = protobuf.lookup("protocol.Message")
  32. const messagePB = message.create(data)
  33. socket.value.send(message.encode(messagePB).finish())
  34. }
  35. self.serverTimeoutObj = setTimeout(() => {
  36. _num--
  37. if (_num <= 0) {
  38. console.log("the ping num is more then 3, close socket!")
  39. socket.value?.close()
  40. }
  41. }, self.timeout)
  42. }, this.timeout)
  43. }
  44. }
  45. // 连接WebSocket
  46. const connect = (userUuid) => {
  47. console.log("开始连接...")
  48. peer.value = new RTCPeerConnection()
  49. socket.value = new WebSocket(`ws://192.168.0.59:8888/api/v1/socket.io?user=${userUuid}`)
  50. socket.value.onopen = () => {
  51. heartCheck.start()
  52. console.log("链接")
  53. webrtcConnection()
  54. }
  55. socket.value.onmessage = (event) => {
  56. heartCheck.start()
  57. handleMessage(event.data)
  58. }
  59. socket.value.onclose = () => {
  60. console.log("关闭并重新连接-->--->")
  61. reconnect()
  62. }
  63. socket.value.onerror = () => {
  64. console.log("error----->>>>")
  65. reconnect()
  66. }
  67. }
  68. // 处理接收到的消息
  69. const handleMessage = (data) => {
  70. const messageProto = protobuf.lookupType("protocol.Message")
  71. const reader = new FileReader()
  72. reader.readAsArrayBuffer(data)
  73. reader.onload = (event) => {
  74. const messagePB = messageProto.decode(new Uint8Array(event.target?.result))
  75. // 单独解码
  76. console.log(messagePB)
  77. if (messagePB.type === "heatbeat") return
  78. if (messagePB.type === Constant.MESSAGE_TRANS_TYPE) {
  79. dealWebRtcMessage(messagePB)
  80. return
  81. }
  82. // 其他消息处理...
  83. }
  84. }
  85. // WebRTC 连接
  86. const webrtcConnection = () => {
  87. if (!peer.value) return
  88. peer.value.onicecandidate = (e) => {
  89. if (e.candidate && socket.value) {
  90. const candidate = {
  91. type: 'answer_ice',
  92. iceCandidate: e.candidate
  93. }
  94. const message = {
  95. content: JSON.stringify(candidate),
  96. type: Constant.MESSAGE_TRANS_TYPE,
  97. }
  98. sendMessage(message)
  99. }
  100. }
  101. peer.value.ontrack = (e) => {
  102. if (e && e.streams) {
  103. const remoteVideo = document.getElementById("remoteVideoReceiver")
  104. const remoteAudio = document.getElementById("audioPhone")
  105. if (remoteVideo) remoteVideo.srcObject = e.streams[0]
  106. if (remoteAudio) remoteAudio.srcObject = e.streams[0]
  107. }
  108. }
  109. }
  110. // 处理WebRTC消息
  111. const dealWebRtcMessage = (messagePB) => {
  112. // 实现与React版本相同的逻辑
  113. }
  114. // 重新连接
  115. const reconnect = () => {
  116. if (lockConnection.value) return
  117. lockConnection.value = true
  118. setTimeout(() => {
  119. if (socket.value?.readyState !== 1) {
  120. connect(localStorage.uuid)
  121. }
  122. lockConnection.value = false
  123. }, 10000)
  124. }
  125. // 发送消息
  126. const sendMessage = (messageData) => {
  127. if (!socket.value) return
  128. const data = {
  129. ...messageData,
  130. fromUsername: localStorage.username,
  131. from: localStorage.uuid,
  132. }
  133. const message = protobuf.lookup("protocol.Message")
  134. const messagePB = message.create(data)
  135. socket.value.send(message.encode(messagePB).finish())
  136. }
  137. // 关闭连接
  138. const close = () => {
  139. socket.value?.close()
  140. peer.value?.close()
  141. socket.value = null
  142. peer.value = null
  143. }
  144. return {
  145. socket,
  146. peer,
  147. connect,
  148. sendMessage,
  149. close,
  150. dealWebRtcMessage,
  151. webrtcConnection
  152. }
  153. })