websocket心跳实现

简介

在实际项目中可能会使用到websocket,在使用过程中可能会存在一种问题就是,当网络异常断开时、或者websocket服务波动时,websocket会断开,导致异常,正常情况下,我们会采用心跳的方式来保持与服务器之间的通信,即客户端向服务端相互发送消息,正常情况下我们都会发送ping、pong消息。下面将使用python和简单的html进行简单的实现。

python部分

主要是实现websocket服务端


from flask import Flask
from flask_sockets import Sockets

app = Flask(__name__)
sockets = Sockets(app)


@sockets.route("/start_websocket")
def start_websocket(ws):
    print("ws:{}".format(ws))
    try:
        while not ws.closed:
            data = ws.receive()
            print("receive_data:{}".format(data))
            if data == 'ping':
                ws.send('pong')
            else:
                ws.send(data)
            ws.send('test')
    except Exception as e:
        print("receive_data error:{}".format(e))


if __name__ == "__main__":
    from gevent import pywsgi
    from geventwebsocket.handler import WebSocketHandler
    server = pywsgi.WSGIServer(listener=("0.0.0.0", 5050), application=app, handler_class=WebSocketHandler)
    server.serve_forever()

前端部分

实现websocket客户端并实现心跳

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>index</title>
</head>
<body>
    <script>
        window.onload=function() {
            var ws = createWebSocket()
            print("ws:", ws)
            var timeout = 5000
            var heartCheck = {
                sendTimeoutObj:null,
                serverTimeoutObj:null,
                // 重置心跳发送
                reset: function() {
                    clearTimeout(this.sendTimeoutObj)
                    clearTimeout(this.serverTimeoutObj)
                },
                // 发送心跳
                start: function() {
                    // 定时发送心跳
                    this.sendTimeoutObj = setTimeout(()=>{
                        ws.send('ping')
                        // 正常来说,当发送完心跳包后,服务端会响应即在onmessage中做出响应,并清除此心跳包发送新的心跳包,
                        // 如果没有做出响应的,则达到超时时间主动关闭websocket,开始重连
                        this.serverTimeoutObj = setTimeout(()=> {
                            ws.close()
                        }, timeout)
                    }, timeout)
                }
            }

            // 创建websocket
            function createWebSocket() {
                try{
                    var ws = new WebSocket("ws://127.0.0.1:5050/start_websocket")
                    init(ws)
                    return ws
                } catch(e) {
                    console.log("connect exception")
                    return null
                } 
            }

            // 初始化websocket
            function init(ws) {
                // websocket打开时
                ws.onopen = function() {
                    console.log("WebSocket open")
                    heartCheck.reset()
                    heartCheck.start()
                }
                ws.onclose = function(response) {
                    console.log("onclose:", response)
                    reconnect()
                }
                // 接收消息
                ws.onmessage = function(response) {
                    console.log("onmessage:", response)
                    heartCheck.reset()
                    heartCheck.start()
                }
                ws.onerror = function(response) {
                    console.log("onerror:", response)
                }
            }
            
            var isConnected = false
            var reconnectTimeout = null
            // 重连
            function reconnect() {
                // 当前正在操作连接的时候就不进行连接,防止出现重复连接的情况
                if (isConnected) return
                isConnected = true
                reconnectTimeout && clearTimeout(reconnectTimeout)
                reconnectTimeout = setTimeout(()=>{
                    heartCheck.reset()
                    isConnected = false
                    ws = createWebSocket()  
                }, timeout)
              
            }
        }
    </script>
</body>
</html>

简易的示意图

image
image

posted @   形同陌路love  阅读(2703)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示