Hi,
I am just connecting the users to websocket and returning the list of all connected users.
When i connect the first user everything works fine. But once i connect another user I get the following error:
Traceback (most recent call last):
File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 154, in run_asgi
result = await self.app(self.scope, self.asgi_receive, self.asgi_send)
File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
return await self.app(scope, receive, send)
File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/fastapi/applications.py", line 179, in __call__
await super().__call__(scope, receive, send)
File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/starlette/applications.py", line 111, in __call__
await self.middleware_stack(scope, receive, send)
File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/starlette/middleware/errors.py", line 146, in __call__
await self.app(scope, receive, send)
File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/starlette/exceptions.py", line 58, in __call__
await self.app(scope, receive, send)
File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/starlette/routing.py", line 566, in __call__
await route.handle(scope, receive, send)
File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/starlette/routing.py", line 283, in handle
await self.app(scope, receive, send)
File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/starlette/routing.py", line 57, in app
await func(session)
File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/fastapi/routing.py", line 228, in app
await dependant.call(**values)
File "./main.py", line 110, in connect_user
await socket_manager.get_online_users()
File "./users/views.py", line 224, in get_online_users
await connection[0].send_json({"sender": response.get('sender')})
File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/starlette/websockets.py", line 137, in send_json
await self.send({"type": "websocket.send", "text": text})
File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/starlette/websockets.py", line 68, in send
await self._send(message)
File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 231, in asgi_send
raise RuntimeError(msg % message_type)
RuntimeError: Unexpected ASGI message 'websocket.send', after sending 'websocket.close'.
I found this issue but that doesn't work in my case.
websocket manager:
class SocketManager:
def __init__(self):
self.active_connections: List[(WebSocket, models.User)] = []
async def connect(self, websocket: WebSocket, user: models.User):
await websocket.accept()
self.active_connections.append((websocket, user))
async def get_online_users(self):
response = {"receivers": []}
for connection in self.active_connections:
response['receivers'].append(connection[1].username)
for connection in self.active_connections:
response.update({"sender": connection[1].username})
# this is causing the problem
await connection[0].send_json(response)
websocket endpoint
socket_manager = SocketManager()
@app.websocket("/api/user-connect")
async def connect_user(websocket: views.WebSocket, db: Session = Depends(get_db)):
user = views.get_current_user(db, websocket.cookies.get("access_token"))
if user:
# connect user to a websocket
await socket_manager.connect(websocket, user)
# broadcast the connected list of users.
await socket_manager.get_online_users()
JavaScript code:
var socket = new WebSocket("ws://127.0.0.1:8000/api/user-connect");
socket.onmessage = function(event) {
var data = JSON.parse(event.data);
var sender = data['sender'];
console.log(sender);
}
Are you using python for connecting the two users to the websocket endpoint? If so please post this code as well.
I have seen similar issues when my client did not send the appropriate websocket "ping"s for the server to "pong", a keep alive mechanism used to make sure a client still exists so the connection does not close.
@codemation I am using javascript to create a websocket on frontend please check question i edited it.
If I had to guess, I'd say after your connect_user function exits, your websocket closes, so your socket manager just tries to send messages to closed sockets.
You probably want a loop recieving messages at the end of it instead
@Mause This fixed the problem :)
@app.websocket("/api/user-connect")
async def connect_user(websocket: views.WebSocket, db: Session = Depends(get_db)):
user = views.get_current_user(db, websocket.cookies.get("access_token"))
if user:
await socket_manager.connect(websocket, user)
await socket_manager.get_online_users()
try:
while True:
data = await websocket.receive_json()
print(data)
except WebSocketDisconnect:
socket_manager.disconnect(websocket, user)
Most helpful comment
If I had to guess, I'd say after your connect_user function exits, your websocket closes, so your socket manager just tries to send messages to closed sockets.
You probably want a loop recieving messages at the end of it instead