Python & FastAPI, 使用websocket时,recive_text()会一直阻塞直到收到从浏览器的数据

当使用websocket进行实时显示数据时,由于接收数据会阻塞线程,而此时await send_text(msg)

无法发送,如果在新的线程中调用发送,是无法调用await send_text()函数的,而如果在recv_text()后再发送,因为recive_text()会阻塞,致使之后服务器不断推送的数据无法发送,所以,经过多方尝试后,可以使用心跳的方式巧妙地实现不断的推送,在web浏览器端,不断的发送心跳,而在服务器端,当接收到的是心跳的信息后,跳过转发指令,直接读取数据。

如下:

服务端:

@app.websocket("/ws/{client_id}")
async def websocket_endpoint(websocket: WebSocket, client_id: str):
    global manager
    global isWhile
    await manager.connect(client_id,websocket)
    print("client %s: connected." % client_id)
    try:
        while True:
            dataFromExplor = await manager.recivemessage(websocket) #从网页socket中获取到的值;
            jsonData = json.loads(dataFromExplor) #json字符串解析成json对象;
            if jsonData["cmd"] != "Heart.Beat": #若不是心跳,则需要将指令发送出去;通过心跳机制,以使recv不再完全阻塞,疏通了接收数据。
                channelPacket = packetChannelData(client_id,jsonData,{}) #以 真实数据长度(4字节) + 真实数据(json字符串) 的格式进行封装;
                manager.sendDataToWebServer(channelPacket) #通过管道将数据发送给TcpSocket线程;
            await manager.trySendFromWebServer() #尝试接收返回的数据并发送回web浏览器客户端;
    except WebSocketDisconnect:
        print("client %s exit!" % client_id)
        manager.disconnect(client_id,websocket)

客户端:

var ws
    var timerId = -1
    window.onload = function()
    {
        if(timerId >= 0){
            window.clearInterval(timerId) //先关闭之前的定时器;
        }
        if ("WebSocket" in window){ //表明此浏览器支持 WebSocket!
            // 打开一个 web socket;
            var client_id = document.getElementById("username").value + "."+Date.now()
            ws = new WebSocket(`ws://192.168.110.37:8001/ws/${client_id}`);
            ws.onopen = function(){ //表明WebSocket已连接上;
                //alert("连接成功!");
                var cmdJson = {"cmd":"Fetch.Clients","params":{}}
                ws.send(JSON.stringify(cmdJson))
                timerId = self.setInterval("heartbeat()",100)
            }
            ws.onmessage = function(event){ //当服务器推送消息时,浏览器收到消息;
                var msg = event.data
                //alert(msg)
                var obj = JSON.parse(msg)
                var cmd = obj['query']['cmd']
                var reply = obj['reply'] //jsonObject;
                if(cmd == "Fetch.Clients"){
                    document.getElementById("client_ids").innerHTML = JSON.stringify(reply)
                    return;
                }

                if(cmd == "Session.Error"){
                    document.getElementById("session_errmsg").innerHTML = JSON.stringify(reply)
                    return ;
                }
                if(cmd == "Session.Status"){
                    document.getElementById("session_status").innerHTML = JSON.stringify(reply)
                    return ;
                }
                if(cmd == "Session.System"){
                    document.getElementById("session_sys").innerHTML = JSON.stringify(reply)
                    return ;
                }
                if(cmd == "Session.Zone"){
                    document.getElementById("session_zone").innerHTML = JSON.stringify(reply)
                    return ;
                }
                if(cmd == "Session.Alarm"){
                    document.getElementById("session_alarm").innerHTML = JSON.stringify(reply)
                    return ;
                }
                if(cmd == "Session.Profile"){
                    document.getElementById("session_profile").innerHTML = JSON.stringify(reply)
                    return ;
                }
            };
            ws.onclose = function(){ //关闭WebSocket连接时,可以做些处理;
                //alert("连接已关闭...");
                if(timerId >= 0){
                    window.clearInterval(timerId) //先关闭之前的定时器;
                }
            };
        }
        else { // 浏览器不支持 WebSocket;
            alert("您的浏览器不支持 WebSocket!");
        }
    }
    function heartbeat(){
        var cmdJson = {"cmd":"Heart.Beat","params":{}}
        ws.send(JSON.stringify(cmdJson))
    }

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Python FastAPI 是一个高性能、易于使用、快速编写 API 的 Web 框架。如果你想要在 FastAPI 中增加 WebSocket,可以使用第三方库 fastapi-websocket 来实现。 首先,你需要在你的项目中安装 fastapi-websocket 库。你可以使用 pip 命令进行安装: ``` pip install fastapi-websocket ``` 安装完成后,在你的 FastAPI 项目中导入 fastapi_websocket 包。然后,你可以通过创建一个 WebSocketEndpoint 类来实现 WebSocket: ```python from fastapi import FastAPI from fastapi_websocket import WebSocket app = FastAPI() class WebSocketEndpoint: def __init__(self, ws: WebSocket): self.ws = ws async def send_message(self, message: str): await self.ws.send_text(message) @app.websocket("/ws") async def websocket_endpoint(ws: WebSocket): websocket = WebSocketEndpoint(ws) await websocket.send_message("Hello, WebSocket!") ``` 在上面的代码中,我们创建了一个 WebSocketEndpoint 类来实现 WebSocket。这个类中包含了一个 send_message 方法,用来发送消息给客户端。然后,在 websocket_endpoint 函数中,我们创建了一个 WebSocketEndpoint 对象,并通过 send_message 方法发送一条消息。 最后,我们将这个 WebSocketEndpoint 函数装饰为 /ws 路径的 WebSocket: ```python @app.websocket("/ws") async def websocket_endpoint(ws: WebSocket): websocket = WebSocketEndpoint(ws) await websocket.send_message("Hello, WebSocket!") ``` 如果你想要了解更多关于 FastAPIfastapi-websocket 的内容,可以查看官方文档:https://fastapi.tiangolo.com/tutorial/websockets/

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风尘无名

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值