python - OOP Python 网络套接字

标签 python websocket python-asyncio macos-mojave

我想封装python的功能websockets封装成一个类,代表一个传感器协调器。这样做的目的是允许我创建一个协调器对象,并且只让服务器在需要时持续存在。不幸的是,我无法在网上找到任何类似的例子,并且到目前为止一直在努力。

我的代码如下:

import asyncio
import json
import logging
import websockets

logging.basicConfig()


class Coordinator(object):

    def __init__(self, host='localhost', port=8080):
        self.host = host
        self.port = port

        self.running = False

        self.server = None
        self.sensors = set()

    def __enter__(self):
        self.server = websockets.serve((self.ws_handler, self.host, self.port))
        self.running = True

    def __exit__(self, exc_type, exc_val, exc_tb):
        # Gracefully stop serving
        self.running = False
        pass

    def sensors_event(self):
        return json.dumps({'type': 'sensors', 'count': len(self.sensors)})

    async def notify_sensors(self):
        if self.sensors:
            message = self.sensors_event()
            await asyncio.wait([user.send(message) for user in self.sensors])

    async def register(self, websocket):
        self.sensors.add(websocket)
        await self.notify_sensors()

    async def unregister(self, websocket):
        self.sensors.remove(websocket)
        await self.notify_sensors()

    async def ws_handler(self, websocket):
        try:
            await self.register(websocket)
            pass

        finally:
            await self.unregister(websocket)


if __name__ == '__main__':
    with Coordinator() as coordinator:
        pass

目前 websocket 服务器似乎没有启动,因为它在 netstat 上不可见。

是否可以在由协调器对象持有的单独(恶魔化)线程中运行服务器?

谢谢

最佳答案

来自high-level documentation :

The websockets.server module defines a simple WebSocket server API.

serve() returns an awaitable. Awaiting it yields an instance of WebSocketServer which provides close() and wait_closed() methods for terminating the server and cleaning up its resources.

On Python ≥ 3.5, serve() can also be used as an asynchronous context manager. In this case, the server is shut down when exiting the context.

正如@user4815162342 已经确定的那样,主要问题是您没有等待对 serve() 协程的调用。

由于您使用的是 Python v3.6.8,因此您可以使用异步上下文管理器来简化实现。这样做的好处是您无需担心处理关机,因为它是自动处理的。这是一个简单回显服务器的面向对象实现。

import asyncio
import signal
import websockets

class Server(object):

    def __init__(self, host, port):
        self.host, self.port = host, port
        self.loop = asyncio.get_event_loop()

        self.stop = self.loop.create_future()
        self.loop.add_signal_handler(signal.SIGINT, self.stop.set_result, None)

        self.loop.run_until_complete(self.server())

    async def server(self):
        async with websockets.serve(self.ws_handler, self.host, self.port):
            await self.stop

    async def ws_handler(self, websocket, path):
        msg = await websocket.recv()
        print(f'Received: {msg}')

        await websocket.send(msg)
        print(f'Sending: {msg}')


if __name__ == '__main__':
    server = Server(host='localhost', port=6789)

目前,这将一直运行到用户发送中断为止,但您可以调整 stop future 以适应。

关于python - OOP Python 网络套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54467332/

相关文章:

websocket - 在 Electron 中拦截并回复 WSS 请求

python-3.x - 如何在异步上下文中读取 (hdf5) 文件?

python - 在范围内调用 asyncio Future

python - 类型错误 : can't pickle coroutine objects when i am using asyncio loop. run_in_executor()

处理二进制文件的python性能

python - 导入错误: bad magic number in 'dateparser' : b'\x03\xf3\r\n'

python - Struct.error : argument for 's' must be a bytes object, 已经提供

django - 带有 Django channel 的 Websocket 不工作,连接失败

python - 使用装饰器参数进行切换

java - Jetty - 使用 websockets 和 ByteBuffer 时可能发生内存泄漏