python - 如何停止使用 websockets.serve() 创建的 websocket 服务器?
问题描述
我用这个包https://websockets.readthedocs.io/en/stable/intro.html创建了 websocket serwer 。我必须在运行时停止重新启动此服务器。
我的服务器作为 asyncio.Task 运行,但 cancel() 方法似乎什么都不做。有什么办法可以停止这个服务器任务然后重新启动它?
服务器.py
#!/usr/bin/env python3
import asyncio
import websockets
class App:
def __init__(self):
self._task = None
self._slots = []
async def worker(self, websocket, path):
data = await websocket.recv()
self._slots.append(data)
await websocket.send(f'prev: {"; ".join(self._slots)}')
self.stop_server()
def start_server(self):
self._task = asyncio.ensure_future(websockets.serve(self.worker, 'localhost', 5000))
def stop_server(self):
self._task.cancel() # this doeas not stop server :P
print(self._task.cancelled()) # always False
def run(self):
try:
loop = asyncio.get_event_loop()
self.start_server()
loop.run_forever()
finally:
loop.close()
App().run()
测试客户端
#!/usr/bin/env python
# WS client example
import asyncio
import websockets
async def hello():
async with websockets.connect(
'ws://localhost:5000') as websocket:
name = input("What's your name? ")
await websocket.send(name)
print(f"> {name}")
greeting = await websocket.recv()
print(f"< {greeting}")
asyncio.get_event_loop().run_until_complete(hello())
解决方案
在您提供的链接的部署部分下,有一个正常关闭部分: https ://websockets.readthedocs.io/en/stable/deployment.html#graceful-shutdown
您可能希望在关闭服务器时优雅地关闭连接,可能是在执行一些清理逻辑之后。使用 serve() 返回的对象有两种方法可以实现这一点:
- 将其用作异步上下文管理器,或
- 调用它的 close() 方法,然后等待它的 wait_closed() 方法完成。
在 Unix 系统上,关机通常是通过发送信号来触发的。
这是一个完整的示例(仅限 Unix):
#!/usr/bin/env python
import asyncio
import signal
import websockets
async def echo(websocket, path):
async for message in websocket:
await websocket.send(message)
async def echo_server(stop):
async with websockets.serve(echo, "localhost", 8765):
await stop
loop = asyncio.get_event_loop()
# The stop condition is set when receiving SIGTERM.
stop = loop.create_future()
loop.add_signal_handler(signal.SIGTERM, stop.set_result, None)
# Run the server until the stop condition is met.
loop.run_until_complete(echo_server(stop))
请注意,以上只是一个 Unix 示例。
stop
通过将awaitable替换为以下内容,我在 Windows 上得到了同样的效果:
import threading
stop_event = threading.Event()
stop = asyncio.get_event_loop().run_in_executor(None, stop_event.wait)
然后stop_event.set()
在你想停止服务器时调用
推荐阅读
- airflow - Airflow 使用 ExternalTaskSensor 手动运行 DAG
- c# - 从实体框架中提取列表列表
- python - 传递函数将忽略的参数
- javascript - 如何在 node.js 函数中应用 Promise
- postgresql - 错误:运算符不存在:数字 = 字符变化
- spring - MVC 中的 Spring Cache - 可以使用自动装配进行查找吗?
- .net - Docker 容器启动(“docker run”)但立即停止(ASP .NET MVC api-REST 解决方案)
- java - 使用 Java 在 XML 中设置嵌入字段的文本
- sql - 连接具有相同键的表,第二个表有多个键值,第二个表的行必须具有相同的列值
- jenkins - Docker 上的詹金斯。-- Hello World 示例构建失败