Skip to content

Commit 2f97a44

Browse files
committed
Add API to disconnect clients
1 parent c7b1467 commit 2f97a44

File tree

3 files changed

+52
-9
lines changed

3 files changed

+52
-9
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,10 @@ The WebsocketServer can be initialized with the below parameters.
7979
| `set_fn_message_received()` | Sets a callback function that will be called when a `client` sends a message | function | None |
8080
| `send_message()` | Sends a `message` to a specific `client`. The message is a simple string. | client, message | None |
8181
| `send_message_to_all()` | Sends a `message` to **all** connected clients. The message is a simple string. | message | None |
82-
| `shutdown_gracefully()` | Shutdown server by sending a websocket CLOSE handshake to all connected clients. | None | None |
83-
| `shutdown_abruptly()` | Shutdown server without sending any websocket CLOSE handshake. | None | None |
82+
| `disconnect_clients_gracefully()` | Disconnect all connected clients by sending a websocket CLOSE handshake. | Optional: status, reason | None |
83+
| `disconnect_clients_abruptly()` | Disconnect all connected clients. Clients won't be aware until they try to send some data. | None | None |
84+
| `shutdown_gracefully()` | Disconnect clients with a CLOSE handshake and shutdown server. | Optional: status, reason | None |
85+
| `shutdown_abruptly()` | Disconnect clients and shutdown server with no handshake. | None | None |
8486

8587

8688

tests/test_server.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,29 @@ def test_client_closes_gracefully(self, session):
115115
assert not server.clients
116116
with pytest.raises(BrokenPipeError):
117117
old_client_handler.connection.send(b"test")
118+
119+
def test_disconnect_clients_abruptly(self, session):
120+
client, server = session
121+
assert client.connected
122+
assert server.clients
123+
server.disconnect_clients_abruptly()
124+
assert not server.clients
125+
126+
# Client won't be aware until trying to write more data
127+
with pytest.raises(BrokenPipeError):
128+
for i in range(3):
129+
client.send("test")
130+
sleep(0.2)
131+
132+
def test_disconnect_clients_gracefully(self, session):
133+
client, server = session
134+
assert client.connected
135+
assert server.clients
136+
server.disconnect_clients_gracefully()
137+
assert not server.clients
138+
139+
# Client won't be aware until trying to write more data
140+
with pytest.raises(BrokenPipeError):
141+
for i in range(3):
142+
client.send("test")
143+
sleep(0.2)

websocket_server/websocket_server.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ def shutdown_gracefully(self, status=CLOSE_STATUS_NORMAL, reason=DEFAULT_CLOSE_R
8686
def shutdown_abruptly(self):
8787
self._shutdown_abruptly()
8888

89+
def disconnect_clients_gracefully(self):
90+
self._disconnect_clients_gracefully()
91+
92+
def disconnect_clients_abruptly(self):
93+
self._disconnect_clients_abruptly()
94+
8995

9096
class WebsocketServer(ThreadingMixIn, TCPServer, API):
9197
"""
@@ -196,12 +202,7 @@ def _shutdown_gracefully(self, status=CLOSE_STATUS_NORMAL, reason=DEFAULT_CLOSE_
196202
Send a CLOSE handshake to all connected clients before terminating server
197203
"""
198204
self.keep_alive = False
199-
200-
# Send CLOSE to clients
201-
for client in self.clients:
202-
client["handler"].send_close(CLOSE_STATUS_NORMAL, reason)
203-
204-
self._terminate_client_handlers()
205+
self._disconnect_clients_gracefully(status, reason)
205206
self.server_close()
206207
self.shutdown()
207208

@@ -210,10 +211,24 @@ def _shutdown_abruptly(self):
210211
Terminate server without sending a CLOSE handshake
211212
"""
212213
self.keep_alive = False
213-
self._terminate_client_handlers()
214+
self._disconnect_clients_abruptly()
214215
self.server_close()
215216
self.shutdown()
216217

218+
def _disconnect_clients_gracefully(self, status=CLOSE_STATUS_NORMAL, reason=DEFAULT_CLOSE_REASON):
219+
"""
220+
Terminate clients gracefully without shutting down the server
221+
"""
222+
for client in self.clients:
223+
client["handler"].send_close(CLOSE_STATUS_NORMAL, reason)
224+
self._terminate_client_handlers()
225+
226+
def _disconnect_clients_abruptly(self):
227+
"""
228+
Terminate clients abruptly (no CLOSE handshake) without shutting down the server
229+
"""
230+
self._terminate_client_handlers()
231+
217232

218233
class WebSocketHandler(StreamRequestHandler):
219234

0 commit comments

Comments
 (0)