Websocket问题记录

Aditya2021-06-18开发问题Websocket

提取ws公共方法

会涉及多次创建和取消ws,所以就提取出来,通过mixin方式引入

// /mixins/socket.js
<script>
export default {
name: "socket",
  methods: {
    sleep(){
      return new Promise(resolve => setTimeout(resolve, 100))
    },
    linkWs (type, wsUrl) {
      this.tryStartWs(type, wsUrl)
      this.$on('logout', () => {
        if (this[type + 'Socket']) {
          console.log('close camera socket')
          this.closeWs()
        }
      })
      this.$on('login', () => {
        console.log('start ws call by login')
        this.tryStartWs(type, wsUrl)
      })
    },
    // 尝试ipPorts是否能够成功创建ws
    tryStartWs(type, wsUrl) {
      if (this[type + 'Socket']) {
        console.log('tryStartWs: ws camera close')
        this.closeWs()
      }
      return Promise.race([wsUrl].map(url  => {
        return this.testWsUrl(url)
      })).then(({code, data})=> {

        if (code === 1) {
          this.wsUrl = data
          console.log('start ws camera at: ', this.wsUrl)
          // this.ctaSocket = new WebsocketHeartbeat({url: this.wsCtaUrl})
          this[type + 'Socket'] = new WebSocket(this.wsUrl)
          this[type + 'Socket'].onmessage = this.onWsMessage
          this[type + 'Socket'].onopen = () => {
            this.onInitSend('type')
          }
          return this[type + 'Socket']
        }
        return new Error('start ws failed: can not connect', code, data)
      })
    },
    testWsUrl(url, payload = 5000) {
      let timer = exec => setTimeout(exec, payload)

      return new Promise((res) => {
        // let socket = new WebsocketHeartbeat({url})
        let socket = new WebSocket(url)

        socket.onopen = function () {
          socket.close()
          res({code: 1, data: url})
        }
        socket.onintialfailed = function (err) {
          // console.log('intailFialed--->', err)
          socket.close()
          // 保证失败的时候时间至少是payload
          timer(() => {
            res({code: -1, data: err})
          })
        }
        socket.onerror = function (err) {
          // console.log('onerror-->', err)
          socket.close()
          // 保证失败的时候时间至少是payload
          timer(() => {
            res({code: -2, data: err})
          })
        }
      })
    },
    closeWs(type) {
      let socket = this[type + 'Socket']
      if (socket) {
        socket.close()
        socket = null
      }
    }
  }
}
</script>

ws引入

// index.vue
import socket from "@/mixins/socket";
export default {
  mixins: [socket],
  created() {
    this.linkWs('upload', 'ws://192.168.5.201:8080/ws/communication/upload')
  },
  methods: {
    onInitSend () {

    },
    onWsMessage(params) {
      console.log('receive:', data)
    }
  },
  beforeDestroy() {
    this.closeWs('upload')
  }
}
</script>
  • 连接到ws时,需要一次性多次send,如果不加sleep间隔的话,会把后端的服务器干崩

  • 及时断开ws连接,后端的ws连接数上限也会有问题

通过ws上传文件

onUpdate(obj) {
  let file = obj.file
  console.log(file)
  const reader = new FileReader();
  reader.readAsArrayBuffer(file);//以二进制形式读取文件
  //文件读取完毕后该函数响应
  reader.onload = async (evt) => {
    // let ext = file.name.split(".")[1];
    // console.log(ext)
    this.uploadSocket.send(`set/upgrade=${file.name}`)
    let blob = evt.target.result;
    await this.sleep()
    this.uploadSocket.send(blob);
    console.log("finish");
  }
}

上传约定方法是先发送这次是什么类型,并告知文件名称,再传输文件

下载ws传输文件

onWsMessage(params) {
  let data = params.data
  if (typeof data === 'string') {
    this.logName = data
  } else {
    let a = document.createElement('a')
    let blob = new Blob([data], {type: 'application/zip'})
    let url = window.URL.createObjectURL(blob)

    a.setAttribute('download', this.logName)
    a.href = url
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    window.URL.revokeObjectURL(url)
  }
}
const data = fs.readFileSync('yarn-error.log');
client.send(data);

wfs.js处理h264裸流

wfs.js下载地址open in new window

<video ref="video" id="video" controls></video></div>

this.$nextTick(() => {
  if (Wfs.isSupported()) {
    this.wfs = new Wfs()
    this.wfs.attachMedia(this.$refs.video,'ch1')
    }
  })

// 断开
this.wfs.destory()

需要注意的是在该库中直接修改ws地址

key: 'onMediaAttached',
value: function onMediaAttached(data) {
    console.log(data)
    if (data.websocketName != undefined) {
        var client = new WebSocket('ws://192.168.5.201:8080/ws/communication/h264video');
        this.wfs.attachWebsocket(client, data.channelName);
    } else {
        console.log('websocketName ERROE!!!');
    }
}

The play() request was interrupted by a call to pause().

Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause(). 在使用wfs.js库的时候,部分浏览器出现了该问题。

我看大部分的解决方案是

this.media.load()
let playPromise = this.media.play()

if (playPromise !== undefined) {
    playPromise.then(_ => {
        this.media.play();
    })
    .catch(error => {
        console.log(error)
    });
}

但还是没解决问题,加了load后反而会报错。

Last Updated 2024/12/27 11:36:49