WebSocket:如何在它死后自动重新连接

IT技术 javascript websocket
2021-03-19 14:36:46
var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function () {
  ws.send(JSON.stringify({
      .... some message the I must send when I connect ....
  }));

};

ws.onmessage = function (e) {
  console.log('Got a message')
  console.log(e.data);
};

ws.onclose = function(e) {  
  console.log('socket closed try again'); 

}

ws.onerror = function(err) {
  console.error(err)
};

当我第一次连接到套接字时,我必须首先向服务器发送一条消息来验证自己并订阅频道。

我遇到的问题是有时套接字服务器不可靠并且会触发对象onerroronclose事件'ws'

问题:有什么好的设计模式可以让我,每当套接字关闭或遇到错误时,等待 10 秒钟,然后重新连接到套接字服务器(并将初始消息重新发送到服务器)

6个回答

这就是我的结果。它适用于我的目的。

function connect() {
  var ws = new WebSocket('ws://localhost:8080');
  ws.onopen = function() {
    // subscribe to some channels
    ws.send(JSON.stringify({
        //.... some message the I must send when I connect ....
    }));
  };

  ws.onmessage = function(e) {
    console.log('Message:', e.data);
  };

  ws.onclose = function(e) {
    console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason);
    setTimeout(function() {
      connect();
    }, 1000);
  };

  ws.onerror = function(err) {
    console.error('Socket encountered error: ', err.message, 'Closing socket');
    ws.close();
  };
}

connect();
这是否会重新连接到之前连接的同一个 websocket?因为我使用 websocket id 发送消息,但是如果它有新的 websocket id,就很难将消息发送到特定系统。
2021-04-21 14:36:46
我在这段代码中看到的问题是,如果连接关闭并且我们尝试再次打开连接,但它失败了,那么我们将永远不会发出重试。
2021-04-25 14:36:46
当连接关闭时 websocket 实例会发生什么。是垃圾收集,还是浏览器建立了一堆未使用的对象?
2021-04-27 14:36:46
setTimeout(connect,1000) 是一种更简洁、资源高效的延迟重新连接方式。还可以考虑使用 setTimeout (connect ,Math.min(10000,timeout+=timeout)),在第一次连接之前和每次成功连接之后将超时重置为 250。这种方式连接期间的错误情况会增加退避,但如果是一次性错误情况,则会快速重新连接 - 250,500,1000,2000,4000,8000,10000,10000 毫秒延迟不那么激进,但响应速度比 1000,1000 快,1000 毫秒
2021-05-12 14:36:46
@AlexanderDunaev,超时主要是作为一种简单的方法来避免服务器不可用时过于激进的重新连接,即网络中断或本地调试服务器关闭。但总的来说,我认为立即重新连接然后重新连接的等待时间呈指数增长会比固定的 1 秒等待稍好一些。
2021-05-13 14:36:46

这对我有用setInterval,因为客户端连接可能会丢失。

ngOnInit(): void {
    if (window.location.protocol.includes('https')) {
        this.protocol = 'wss';
    }

    this.listenChanges();
}


listenChanges(): void {
    this.socket = new WebSocket(`${this.protocol}://${window.location.host}/v1.0/your/url`);

    this.socket.onmessage = (event): void => {
        // your subscription stuff
        this.store.dispatch(someAction);
    };

    this.socket.onerror = (): void => {
        this.socket.close();
    };


    this.socket.onopen = (): void => {
        clearInterval(this.timerId);

        this.socket.onclose = (): void => {
            this.timerId = setInterval(() => {
                this.listenChanges();
            }, 10000);
        };
    };
}

不要忘记clearInterval在套接字打开时调用

这不是一个明确的react问题,但这是一个react风格的答案:

TLDR:您可以使用setInterval定期检查 websocket 连接状态,如果连接关闭,则尝试重新连接。https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState

class TestComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};

    this.connect = this.connect.bind(this);
  }

  componentDidMount() {
    this.interval = setInterval(this.connect, 1000);
  }

  componentWillUnmount() {
    if (this.ws) this.ws.close();
    if (this.interval) clearInterval(this.interval);
  }

  connect() {
    // https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
    if (this.ws === undefined || (this.ws && this.ws.readyState === 3)) {
      this.ws = new WebSocket(`ws://localhost:8080`);

      this.ws.onmessage = (e) => {
        console.log(JSON.parse(e.data));
      };
    }
  }

  render() {
    return <div>Hey!</div>;
  }
}

在本机 Websocket api 之上的一个太有趣的包装器来添加它并且很好地

https://github.com/joewalnes/reconnecting-websocket

如果套接字关闭或服务器上发生任何错误,则使用 async-await 客户端将尝试每 5 秒自动连接一次,永远看看我的答案