如何停止使用websockets.serve()创建的websocket服务器?

时间:2019-06-19 08:22:56

标签: python websocket python-asyncio

我使用此软件包https://websockets.readthedocs.io/en/stable/intro.html创建了websocket服务器。我必须在运行时停止重新启动该服务器。

我的服务器以asyncio.Task的身份运行,但是cancel()方法似乎无能为力。 有什么办法可以停止此服务器任务,然后再重新启动它?

server.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())

1 个答案:

答案 0 :(得分:0)

在您提供的链接的“部署”部分下,有一个“正常关机”部分: 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示例。

我将Windows上的stop替换为以下内容,从而在Windows上也能做到这一点:

import threading
stop_event = threading.Event()
stop = asyncio.get_event_loop().run_in_executor(None, stop_event.wait)

然后,当您要停止服务器时,只需致电stop_event.set()