likes
comments
collection
share

websocket中Node.js中的应用

作者站长头像
站长
· 阅读数 20

简介

WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。

它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

其他特点包括:

(1)建立在 TCP 协议之上,服务器端的实现比较容易。

(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

(3)数据格式比较轻量,性能开销小,通信高效。

(4)可以发送文本,也可以发送二进制数据。

(5)没有同源限制,客户端可以与任意服务器通信。

(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

readyState

ConstantValueDescription
CONNECTING0The connection is not yet open.
OPEN1The connection is open and ready to communicate.
CLOSING2The connection is in the process of closing.
CLOSED3The connection is closed.
坑点: websocket.readyState ===3 这里 没有走 close 的生命周期

断线重连解决方案

  1. 在websocket/ws 这个框架中,会有open,message,close 和 error生命周期。
  2. 可以在 close 的生命周期中,执行reconnect流程参考最高赞答案.然后在error的生命周期中 打印crash日志,由于 error 必定触发close 所以只需要在 close 生命周期中进行 reconnect方法。

    ws.on("close", function close() {
     console.log("ai connect close");
     reconnect(); /// 每隔5s 重连 
    });
    ws.on("error", function error(error) {
     console.log("ai connect error", error);
     errorLogger.error("ai connect error", error); //打印crash日志
     ws.close()
    });
  3. readyState=3 不会触发close的生命周期,所以需要对其单独处理,一旦检测到 其为3,则 terminate()该websocket.当然还有一种解决方案,因为在websocket中有心跳包的存在,详见How to detect and close broken connections?,可以在接收到来自其他socketServer的'pong'的信号,则写一个定时器,如果规定时间内,没有收到来自下一个的心跳包则 terminate 该socket

    if (message === 'pong') {
         clearTimeout(aliveInterval);
         aliveInterval = setTimeout(function () {
             wsObj.wsAI.terminate()
         }, 10000 + 1000)
    }

ws/websocket 官方Tip: Use WebSocket#terminate(), which immediately destroys the connection,instead of WebSocket#close(), which waits for the close timer. 之我的理解: terminate() 能够立马 destory 连接,如果是close()的话,意味着还需要等待 close 的任务

工程化 Tips:

  • 当我们搭建 websocketServer的时候,常常会遇到socket.readyState =0 的情况, 会报Error: WebSocket is not open: readyState 0 (CONNECTING)这个错误,所以在我们和每个socket通信的时候,可以增加前提 ws.readyState===1 才进行ws.send(),否则socket中断,如何socket发送方没有做socket重连的话,会导致服务的崩溃。
  • 我们可以实时检测是否有 readyState ===2 或者 readyState ===3 的socket连接,主动去执行ws.terminate(),因为在实战的过程中,发现某个socket状态持续为 2(即closing),而不是3(closed)

最后 放上两个websocket的nodejs的框架

1 https://socket.io/

  1. https://github.com/websockets/ws