FastAPI - Websockets,一个客户端多个连接

6ljaweal  于 5个月前  发布在  其他
关注(0)|答案(2)|浏览(85)

尝试在我的fastapi应用程序中实现websockets,然而,当我从JavaScript端连接到websocket时,它打开了4个连接,我在后端端实现了一个解决方案,检查某个客户是否连接,然而这意味着客户端无法连接到移动的上的websocket,而它在计算机上打开。

class ConnectionManager:
    def __init__(self):
        self.connections: dict[int, WebSocket] = {}

    async def connect(self, websocket, customer_id):
        existing_connection = self.connections.get(customer_id)
        if existing_connection:
            await websocket.close()
            raise ExistingConnectionError("Existing connection for customer_id")

        await websocket.accept()
        websocket.customer_id = customer_id
        self.connections[customer_id] = websocket
        print(list(self.connections.values()))

    async def disconnect(self, websocket):
        customer_id = getattr(websocket, 'customer_id', None)
        if customer_id in self.connections:
            del self.connections[customer_id]

    async def broadcast(self, message):
        for websocket in self.connections.values():
            await websocket.send_json(message)

    async def broadcast_to_customer(self, customer_id, message):
        matching_connection = self.connections.get(customer_id)
        if matching_connection:
            await matching_connection.send_json(message)

connection_manager = ConnectionManager()

个字符
JavaScript语言:

let socket;

    if (!socket || socket.readyState !== WebSocket.OPEN) {
        socket = new WebSocket(`ws://localhost:3002/sock?customer_id=${customer_id}`);

        socket.onopen = () => {
            console.log('Connected to WebSocket server');
        };

        let i = 0;

        socket.onmessage = (event) => {
            const data = JSON.parse(event.data);
            console.log('Incoming data:', data);
            console.log('i:', i);
            i = i + 1;
        };
    }


后端日志:

INFO:     connection open
INFO:     ('127.0.0.1', 33366) - "WebSocket /sock?customer_id=185" 403
Existing connection detected, rejecting the new connection
INFO:     connection rejected (403 Forbidden)
INFO:     connection closed
INFO:     ('127.0.0.1', 33368) - "WebSocket /sock?customer_id=185" 403
Existing connection detected, rejecting the new connection
INFO:     connection rejected (403 Forbidden)
INFO:     connection closed
INFO:     ('127.0.0.1', 33384) - "WebSocket /sock?customer_id=185" 403
Existing connection detected, rejecting the new connection
INFO:     connection rejected (403 Forbidden)
INFO:     connection closed


前端日志:

Connected to WebSocket server
Firefox can’t establish a connection to the server at ws://localhost:3002/sock?customer_id=185.
Firefox can’t establish a connection to the server at ws://localhost:3002/sock?customer_id=185.
Firefox can’t establish a connection to the server at ws://localhost:3002/sock?customer_id=185.


尝试在FastAPI中实现WebSocket,为每个客户端打开多个连接而不是一个连接。

7hiiyaii

7hiiyaii1#

我认为你需要这样的东西:
在每个客户端的每个设备的后端存储连接上:

class ConnectionManager:
    def __init__(self):
        self.clients: dict[int, dict[str, WebSocket]] = {}

    async def connect(self, websocket, customer_id, device_hash):
        client_connections = self.clients.get(customer_id)
        if client_connections:
            client_device_connection = client_connections.get(device_hash)
            if client_device_connection:
                await websocket.close()
                raise ExistingConnectionError("Existing connection for customer_id")
        else:
            self.clients[customer_id] = {}

        await websocket.accept()
        websocket.customer_id = customer_id
        websocket.device_hash = device_hash

        self.clients[customer_id][device_hash] = websocket
        print(list(self.clients.values()))

    async def disconnect(self, websocket):
        customer_id = getattr(websocket, 'customer_id', None)
        device_hash = getattr(websocket, 'device_hash', None)
        client_connections = self.clients.get(customer_id)
        if client_connections:
            if client_connections.get(device_hash):
                client_connections.pop(device_hash)

    async def broadcast(self, message):
        for client_connections in self.clients.values():
            for websocket in client_connections.values():
                await websocket.send_json(message)

    async def broadcast_to_customer(self, customer_id, message):
        client_connections = self.client.get(customer_id)
        if client_connections:
            for connection in client_connections.values():
                await connection.send_json(message)

connection_manager = ConnectionManager()

@app.websocket("/sock")
async def websocket_endpoint(websocket: WebSocket, customer_id: int, device_hash: str):

    try:
        await connection_manager.connect(websocket, customer_id, device_hash)
        while True:
            data = await websocket.receive_json()
    except WebSocketDisconnect:
        await connection_manager.disconnect(websocket)
    except ExistingConnectionError:
        print("Existing connection detected, rejecting the new connection")

字符串
当您从前端连接到WebSocket时,添加额外的查询参数device_hash,该参数对于每个用户设备都应该是唯一的。您也可以在服务器端从请求头生成此device_hash(例如,您可以使用user-agent

5f0d552i

5f0d552i2#

此问题可能与您如何检查前端上现有的WebSocket连接有关。
在你的JavaScript代码中,你每次都在创建一个新的WebSocket连接,而没有检查连接是否已经存在。为了确保只建立一个WebSocket连接,你应该以不同的方式处理WebSocket创建逻辑。一种方法是只在WebSocket不存在或不处于打开状态时才创建WebSocket。JavaScript代码的示例修改:

let socket;

// Check if the socket is undefined or not open
if (!socket || socket.readyState !== WebSocket.OPEN) {
    // Create a new WebSocket connection
    socket = new WebSocket(`ws://localhost:3002/sock?customer_id=${customer_id}`);

    socket.onopen = () => {
        console.log('Connected to WebSocket server');
    };

    socket.onmessage = (event) => {
        const data = JSON.parse(event.data);
        console.log('Incoming data:', data);
    };

    socket.onclose = (event) => {
        console.log('WebSocket closed:', event);
    };
}

字符串
此修改可确保仅在不存在现有连接或现有连接未处于打开状态时才创建新的WebSocket连接。
您可能希望处理onclose事件以处理WebSocket连接意外关闭的情况。

相关问题