You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Python Web框架Quart中实现WebSocket客户端的注册与注销?

Handling WebSocket Client Registration/Unregistration in Quart

Got it, let's refine your approach to fit Quart's WebSocket system perfectly. The example you found is close, but Quart uses a slightly different handler structure, and we can make this more robust.

First, a quick callout: using a set instead of a list is smarter here—sets automatically handle duplicate connections, and adding/removing entries is faster than with lists.

Here's a complete, working implementation:

from quart import Quart, websocket
import asyncio

app = Quart(__name__)
# Store connected clients in a set attached to the app instance (cleaner than globals)
app.connected_clients = set()

@app.websocket('/ws')
async def ws_handler():
    # Register the new client: get the actual WebSocket object (Quart uses a proxy)
    current_ws = websocket._get_current_object()
    app.connected_clients.add(current_ws)
    
    try:
        # Example: Broadcast a "new client joined" update to everyone
        await asyncio.gather(*[
            client.send(f"New client connected! Total: {len(app.connected_clients)}")
            for client in app.connected_clients
        ])
        
        # Keep the connection alive and handle incoming messages
        while True:
            incoming_msg = await websocket.receive()
            # Example: Broadcast the received message to all connected clients
            await asyncio.gather(*[
                client.send(f"Someone said: {incoming_msg}")
                for client in app.connected_clients
            ])
    finally:
        # Unregister the client no matter why the connection closes (error, timeout, etc.)
        app.connected_clients.remove(current_ws)
        # Broadcast a "client left" update
        if app.connected_clients:  # Only send if there are remaining clients
            await asyncio.gather(*[
                client.send(f"Client disconnected! Total: {len(app.connected_clients)}")
                for client in app.connected_clients
            ])

if __name__ == '__main__':
    app.run(debug=True)

Key Details to Understand:

  • app.connected_clients over global variables: Tying the client set to the app instance keeps your state organized and avoids issues if you ever run multiple app instances.
  • websocket._get_current_object(): Quart uses a proxy for the websocket variable in handlers, so we need the actual underlying object to store in the set (proxies aren't hashable).
  • try/finally block: This guarantees the client is removed from the set every time the connection closes—whether the client disconnects normally, the network drops, or an error crashes the handler.
  • asyncio.gather(): This is the cleanest way to run multiple send operations concurrently in async code, ensuring all clients get messages without blocking each other.

Testing This Setup:

You can test with a quick JavaScript client in your browser's console:

const ws = new WebSocket('ws://localhost:5000/ws');
ws.onmessage = (event) => console.log(event.data);
ws.send('Hello from the browser!');
// Test disconnection later with: ws.close();

This setup will reliably track all connected clients, add them on connection, and remove them the moment they disconnect.

内容的提问来源于stack exchange,提问作者Dup Dup

火山引擎 最新活动