【问题标题】:Impossible to send websockets message inside of a class无法在类内发送 websockets 消息
【发布时间】:2023-03-28 13:05:01
【问题描述】:

我打算写一个类WebsocketHandler来包装包websockets

这是代码:

import asyncio
import websockets


class WebsocketHandler:
    __connection = None

    def __init__(self):
        asyncio.run(self.__setConnection())

    async def __setConnection(self):
        async with websockets.connect("ws://localhost/your/path") as websocket:
            self.__connection = websocket
            print("Connected")

    def send(self, msg):
        self.__connection.send(msg)
        print("message Send")


ws = WebsocketHandler()
ws.send("message")

对于服务器部分,我有另一个完成的脚本,它可以在我有新连接、收到消息以及客户端断开连接时向我发送消息(与其他语言的其他脚本一起测试)。

当我尝试它时,脚本成功连接到我的 websocket 服务器(脚本打印 Connected 并且在服务器端我得到了一个新连接)。

然后我在脚本中收到警告

RuntimeWarning: coroutine 'WebSocketCommonProtocol.send' was never awaited 
self.__connection.send(msg)

然后我的脚本打印 Message send 并停止。

问题是在服务器端我没有收到消息的事实,而只有一个告诉我客户端已断开连接的消息。基本上脚本不会发送消息,也不会产生错误。

有人知道问题出在哪里吗?

【问题讨论】:

    标签: python asynchronous websocket


    【解决方案1】:

    问题是WebsocketHandler类只有一个异步方法,即__setConnection,通过调用asyncio.run函数运行。 docs 这么说

    这个函数总是创建一个新的事件循环并在 结束。

    也就是说,这是唯一可以运行异步代码的地方。您的代码创建一个 websocket 连接并在打印“已连接”后立即关闭它。发生这种情况是因为您使用 async with 作为异步上下文管理器调用 websockets.connect 方法,它会在退出时自动关闭连接。这是第一个缺陷,第二个缺陷是self.__connection.send 函数是一个协程,在你await 之前它不会运行。这正是错误消息告诉您的内容。以下是修复 websocket 处理程序类的方法:

    import asyncio
    import websockets
    
    
    class WebsocketHandler(object):
    
        def __init__(self):
            self.conn = None
    
        async def connect(self, url):
            self.conn = await websockets.connect(url)
    
        async def send(self, msg):
            await self.conn.send(msg)
    
        async def close(self):
            await self.conn.close()
    
    
    async def main():
        handler = WebsocketHandler()
        await handler.connect('ws://localhost:8765')
    
        await handler.send('hello')
        await handler.send('world')
    
        await handler.close()
    
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    

    【讨论】:

    • 像魅力一样工作 ;) 不得不在我的所有脚本中使用异步只是为了上课的想法让我有点难过,但我想我别无选择
    猜你喜欢
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-21
    • 2021-10-07
    • 2022-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多