Detect a "disconnected" client?
See original GitHub issueHi there. I am wondering if there a way to detect a disconnected client, and somehow kick him from the server? I have a problem if some client disconnect randomly(either by problem at their device or something else), than when i run a check at my server i can see multiple of same type of clients connected!
Is there any way to detect which client are not connected and kick them from the server somehow?
Here is an example of multiple of same clients connected:
ERROR::
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 153, in run_asgi
result = await self.app(self.scope, self.asgi_receive, self.asgi_send)
File "/usr/local/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
return await self.app(scope, receive, send)
File "/usr/local/lib/python3.8/site-packages/fastapi/applications.py", line 149, in __call__
await super().__call__(scope, receive, send)
File "/usr/local/lib/python3.8/site-packages/starlette/applications.py", line 102, in __call__
await self.middleware_stack(scope, receive, send)
File "/usr/local/lib/python3.8/site-packages/starlette/middleware/errors.py", line 146, in __call__
await self.app(scope, receive, send)
File "/usr/local/lib/python3.8/site-packages/starlette/exceptions.py", line 58, in __call__
await self.app(scope, receive, send)
File "/usr/local/lib/python3.8/site-packages/starlette/routing.py", line 550, in __call__
await route.handle(scope, receive, send)
File "/usr/local/lib/python3.8/site-packages/starlette/routing.py", line 283, in handle
await self.app(scope, receive, send)
File "/usr/local/lib/python3.8/site-packages/starlette/routing.py", line 57, in app
await func(session)
File "/usr/local/lib/python3.8/site-packages/fastapi/routing.py", line 242, in app
await dependant.call(**values)
File "./main.py", line 83, in websocket_endpoint
await connection_manager.send_JSON_object_privately_from_object_to_user()
File "./websocket_manager.py", line 285, in send_JSON_object_privately_from_object_to_user
await asyncio.gather(*(conn.ws.send_text(json.dumps(generate_new_JSON)) for conn in self.active_user_client_connections if conn.id == the_user_id))
File "/usr/local/lib/python3.8/site-packages/starlette/websockets.py", line 128, in send_text
await self.send({"type": "websocket.send", "text": data})
File "/usr/local/lib/python3.8/site-packages/starlette/websockets.py", line 68, in send
await self._send(message)
File "/usr/local/lib/python3.8/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 224, in asgi_send
raise RuntimeError(msg % message_type)
RuntimeError: Unexpected ASGI message 'websocket.send', after sending 'websocket.close'.
________________
TERMINAL INFO:
There are currently 0 user clients connected to WEBPAGE
There are currently 4 user clients connected through IPHONE or ANDROID
THE USER CLIENTS :: ['9', '9', '9', '9']
DEVICES:
There are currently 30 Woit-track`s connected to server
WOIT TRACKS CONNECTED: ['DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003', 'DEV003']
I forgot to mention, at some point(maybe after 10 minutes), they slowly gets removed by the list one by one… But i would love to detect this faster…
Here is my code:
#websocket_manager.py
class UserClientWebSocket(BaseModel):
id: str
ws: WebSocket
class Config:
arbitrary_types_allowed = True
class WoitTrackClientWebSocket(BaseModel):
id: str
ws: WebSocket
class Config:
arbitrary_types_allowed = True
class WoitSenseClientSocket(BaseModel):
id: str
ws: WebSocket
class Config:
arbitrary_types_allowed = True
class WebPageClientWebSocket(BaseModel):
id: str
ws: WebSocket
class Config:
arbitrary_types_allowed = True
class ConnectionManager:
def __init__(self):
self.active_user_client_connections: List[UserClientWebSocket] = []
self.collect_user_IDs = []
self.active_webpage_client_connections: List[WebPageClientWebSocket] = []
self.collect_webpages_IDs = []
self.active_woit_track_connections: List[WoitTrackClientWebSocket] = []
self.collect_woit_track_IDs = []
self.active_woit_sense_connections: List[WoitSenseClientSocket] = []
self.collect_woit_sense_IDs = []
async def connect_the_user_client(self, websocket: WebSocket, THE_USER_ID):
await websocket.accept()
if THE_USER_ID not in self.collect_user_IDs:
self.collect_user_IDs.append(THE_USER_ID)
else:
#await self.broadcast_message_to_both_user_and_webpage_clients(f"Somebody connected with the same ID as client: {THE_USER_ID}")
#await self.broadcast_message_to_both_user_and_webpage_clients("but Vlori is a nice and kind guy, so he wil not get kicked :)")
self.collect_user_IDs.append(THE_USER_ID)
self.active_user_client_connections.append(UserClientWebSocket(ws=websocket, id=THE_USER_ID))
await self.send_welcome_message_to_user(f"Dear: {THE_USER_ID}, You have connected to the server, now you just have to subscribe!", THE_USER_ID)
generate_json = {"userID": THE_USER_ID, "subscribe" : 1}
await self.send_welcome_message_to_user(json.dumps(generate_json), THE_USER_ID)
await self.show_number_of_clients()
async def connect_woit_track_client(self, websocket: WebSocket, THE_SENSOR_ID):
await websocket.accept()
if THE_SENSOR_ID not in self.collect_woit_track_IDs:
self.collect_woit_track_IDs.append(THE_SENSOR_ID)
else:
#self.collect_woit_track_IDs.remove(THE_SENSOR_ID)
await self.broadcast_message_to_webpage_clients(f"Somebody connected with the same ID as client: {THE_SENSOR_ID}")
await self.broadcast_message_to_webpage_clients("but Vlori is a nice and kind guy, so he wil not get kicked :)")
self.collect_woit_track_IDs.append(THE_SENSOR_ID)
self.active_woit_track_connections.append(WoitTrackClientWebSocket(ws=websocket, id=THE_SENSOR_ID))
await self.show_number_of_clients()
#main.py:
@app.websocket("/ws/woittrack/{woit_track_id}")
async def websocket_endpoint(websocket: WebSocket, woit_track_id: str):
await connection_manager.connect_woit_track_client(websocket, woit_track_id)
try:
await connection_manager.show_number_of_clients()
try:
while True:
data = await websocket.receive_text()
await receive_JSON_data_from_sensor(data)
await connection_manager.broadcast_message_to_webpage_clients(data)
await connection_manager.broadcast_message_to_webpage_clients("")
await connection_manager.send_JSON_object_privately_from_object_to_user()
except json.JSONDecodeError:
await connection_manager.send_personal_message_to_user("You have not sent JSON object correctly.. fix it plz", websocket)
print(f"Woit-track #{woit_track_id} tries to send JSON object but is not sending it correctly!")
except WebSocketDisconnect as e:
print(f"Woit-track: #{woit_track_id} left the chat", e)
await connection_manager.disconnect_the_woit_track_client(websocket, woit_track_id)
await connection_manager.broadcast_message_to_both_user_and_webpage_clients(f"Woit-track: #{woit_track_id} left the chat")
@app.websocket("/ws/user/{user_id}")
async def websocket_endpoint(websocket: WebSocket, user_id: str):
await connection_manager.connect_the_user_client(websocket, user_id)
await resume_streaming_for_user(user_id)
try:
await connection_manager.show_number_of_clients()
while True:
try:
data = await websocket.receive_json()
userID_from_json = data["userID"]
if userID_from_json == user_id:
await multithread_this_shit(data)
else:
await websocket.send_text(f"_________________________________________________________________________________")
await websocket.send_text(f" userID in json-object is wrong!")
await websocket.send_text(f"the userID inside json object must be the same as the one you are connected with!")
await websocket.send_text(f"_________________________________________________________________________________")
except json.JSONDecodeError as e:
#await connection_manager.send_personal_message_to_user( "You have not sent JSON object correctly.. fix it plz", websocket)
print(f"User #{user_id} tries to send JSON object but is not sending it correctly!")
print(e)
except WebSocketDisconnect as e:
print(f"User-client #{user_id} left the chat", e)
#await remove_user_algorithm_object_from_dictionary(user_id)
await connection_manager.disconnect_the_user_client(websocket, user_id)
await pause_streaming_for_user(user_id)
#await delete_both_user_and_sleep_call_to_sensor_at_once(user_id)
#await connection_manager.broadcast_message_to_both_user_and_webpage_clients(f"User #{user_id} left the chat")
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (1 by maintainers)
Top Results From Across the Web
Instantly detect client disconnection from server socket
This way, I'm able to safely detect disconnection between TCP ... This is only possible if both client and server are under your...
Read more >How to detect closed TCP connection when client ...
These looks promising, answer 3 in .net - Instantly detect client disconnection from server socket - Stack Overflow[^]
Read more >Detecting client disconnections in the server side
You can't really tell if the client is accidentally disconnected, but you can find out with a few seconds by turning on keep-alives....
Read more >How am I supposed to detect client's socket disconnection in ...
The only way to reliably test for disconnection is to have the client periodically send data across the connection. This is called a...
Read more >TCPListener how to detect client socket disconnected - MSDN
So, essentially, you're not really asking the right question. The only way that you know a client has disconnected is that it stops...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
check this code. I’ve changed the
Connection Manager
Class. I hope it helps you.This is coooooooooooooooool! THank you very much