Código de encapsulamento front-end do Websocket, desconexão e reconexão do mecanismo de pulsação

Introdução ao websocket (pode ser ignorado)

Websocket é um link longo de comunicação full-duplex. É usado principalmente para obter comunicação em tempo real e locais com altos requisitos de dados em tempo real. Quando o websocket não aparece, o front-end usa o treinamento de rotação setInterval para atualizar os dados. Nesses locais onde são necessários requisitos de dados em tempo real Ainda podemos usar o treinamento de rotação em áreas de baixa altitude.

(1) Com base no protocolo TCP, a implementação no lado do servidor é relativamente fácil.

(2) Possui boa compatibilidade com o protocolo HTTP. As portas padrão também são 80 e 443, e a fase de handshake usa o protocolo HTTP, portanto não é fácil bloquear durante o handshake e pode passar por vários servidores proxy HTTP.

(3) O formato de dados é relativamente leve, apresenta baixa sobrecarga de desempenho e comunicação eficiente.

(4) Você pode enviar texto ou dados binários.

(5) Não há restrição de origem e o cliente pode se comunicar com qualquer servidor.

(6) O símbolo de protocolo usual é http, enquanto websocket é ws (porta 80 padrão) e a comunicação criptografada é wss (porta padrão 443), que corresponde a https

Links HTTP longos e curtos

As conexões HTTP são divididas em conexões longas e conexões curtas, e o que comumente usamos agora é HTTP1.1, portanto, todos usamos conexões longas. Na verdade, esta frase está apenas parcialmente correta. A maioria dos nossos protocolos HTTP atuais são 1.1, então o que normalmente usamos são basicamente conexões longas. Não existem conexões longas e curtas no protocolo HTTP. O protocolo HTTP é baseado no modelo de solicitação/resposta, portanto, enquanto o servidor responder, a conexão HTTP terminará, ou mais precisamente, a solicitação HTTP terminará. Não existe conexão longa ou curta.

Links TCP longos e curtos

Conexão longa e conexão curta são, na verdade, conexões TCP. A conexão TCP é um canal bidirecional, que pode permanecer aberto por um período de tempo, portanto, a conexão TCP tem conexões realmente longas e conexões curtas. Em última análise, o protocolo HTTP é um protocolo da camada de aplicação, enquanto o TCP é o protocolo da camada de transporte real, apenas a camada responsável pela transmissão precisa estabelecer uma conexão.

Assim como o número do endereço do correio preenchido pela entrega expressa é http, e a ferramenta de transporte correspondente, como o carro, é tcp

mecanismo de pulsação websocket/mecanismo de reconexão de desconexão

Quando a comunicação entre ambas as partes estiver vinculada, se não houver motivos externos, a ligação não será interrompida se as duas partes não se desligarem.

No entanto, existem fatores externos que farão com que o websocket seja interrompido, como: (desconexão da rede, status ruim da rede, o link requer a rede interna e a rede interna não pode estar online, o processo vinculado foi encerrado/o servidor não tem comunicação por muito tempo)

Para garantir que esta comunicação permaneça ativa, precisamos adicionar um mecanismo de pulsação/mecanismo de reconexão de desconexão.

mecanismo de batimento cardíaco

Iniciar pulsação ao estabelecer conexão com o servidor (aberto)

Envie uma mensagem de pulsação ao servidor a cada 30 segundos (ou no horário especificado, 30 segundos é usado temporariamente aqui)⌛Aguarde uma resposta do servidor

Se o front-end receber uma mensagem retornada do servidor dentro dos 30 segundos especificados, ele redefinirá a pulsação e a reiniciará por 30 segundos.

Se nenhuma mensagem for recebida (pode ser por motivos de rede) e o servidor não responder, chame websocke.close() para fechar o link longo e reenviar uma nova solicitação de link para se reconectar ao servidor.

mecanismo de reconexão

Relatamos o erro /close/errno/no response no websokcet respectivamente (aqui o heartbeat chama diretamente close e depois usa close para reconectar)

Encapsular código específico

método de chamada

import { socketContact } from '@/utils/websocket'
const wss = socketContact('/ws/quality_panel/', 'quality panel data', (data) => {
  tableData.value = data // 可以自定义数据处理
})

Código específico da embalagem:

const socketContact = function (contactUrl = '', getDataSecret = '', getDataFn = () => {}) {
  const baseUrl = process.env.VUE_APP_API_WEBSOCKET_URL // baseURL
  const callBack = getDataFn // callback返回数据函数
  const url = contactUrl // 后缀url
  // getDataSecret 需要发送给服务器的数据
  let socket // websocket本体
  let lock = false // 避免重复连接
  let replyOverTime = null // 服务器回复超时setTimeout
  let hearByteTime = null // 心跳 setTimeout
  try {
    socket = new WebSocket(baseUrl + url)
    socket.addEventListener('open', function (event) {
      socket.send(getDataSecret)
      heatByte() // 开始心跳
      console.log('链接成功', contactUrl, getDataSecret)
    })
    socket.addEventListener('message', function (event) {
      resetHardByte() // 重置心跳
      // 这里transporting...' 和'invalid command...'为服务器心跳回复 不做数据返回处理
      if (event.data === 'transporting...' || event.data === 'invalid command...') return
      // 处理服务器返回数据 这里可自定义
      const str = event.data.replaceAll('None', 'null')
      // eslint-disable-next-line no-eval
      const data = eval('(' + str + ')')
      callBack(data)
    });
    socket.addEventListener('close', function (event) {
      console.log('链接关闭', event.code)
      reconnect(url, getDataSecret, callBack) // 尝试重新连接
    });
    socket.addEventListener('errno', function (event) {
      console.log('链接报错')
      reconnect(url, getDataSecret, callBack)// 尝试重新连接
    });
  } catch (e) {
    console.log('catch', e)
    reconnect(url, getDataSecret, callBack) // 尝试重新连接
  }
  function heatByte (type) {
    hearByteTime && clearInterval(hearByteTime)
    replyOverTime && clearInterval(replyOverTime)
    // 每30s一次心跳
    hearByteTime = setTimeout(() => {
      if (socket.readyState === 1) {
        socket.send('heart byte') // 没问题进行心跳
        console.log('heart byte')
      }
      // 重新链接超时 60s无回复 关闭连接 尝试重新链接
      replyOverTime = setTimeout(() => {
        socket.close()
        console.log('网络/其他问题 回复超时间关闭')
      }, 60000)
    }, 30000)
  }
  function resetHardByte () {
    // 进行下一次心跳
    hearByteTime && clearTimeout(hearByteTime)
    replyOverTime && clearTimeout(replyOverTime)
    heatByte()
  }
  function reconnect (url, getDataSecret, callBack) {
    if (lock) return
    lock = true
    setTimeout(() => {
      lock = false
      socketContact(url, getDataSecret, callBack)
      console.log('正在尝试重新连接')
    }, 5000)
  }
  return socket
}

export { socketContact }
referência

Link longo e link curto: http://t.csdn.cn/Ne7g3

websokcet Ruan Yifeng: https://www.ruanyifeng.com/blog/2017/05/websocket.html

websokcet: http://t.csdn.cn/j42h5

Acho que você gosta

Origin blog.csdn.net/weixin_44383533/article/details/129446672
Recomendado
Clasificación