无法在课程内发送websockets消息

时间:2019-10-06 20:53:19

标签: python asynchronous websocket

我计划写一个包装websockets包的类WebsocketHandler

这是代码:

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,它停止了。

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

任何人都知道问题出在哪里吗?

1 个答案:

答案 0 :(得分:2)

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

  

此函数始终创建一个新的事件循环,并在事件循环中将其关闭   结束。

也就是说,这是唯一可以运行异步代码的地方。您的代码会创建一个websocket连接,并在打印“已连接”后立即关闭它。发生这种情况是因为您使用websockets.connect作为异步上下文管理器调用了async with方法,该方法在退出时自动关闭了连接。这是第一个缺陷,第二个缺陷是self.__connection.send函数是一个协程,并且直到您等待之前它都不会运行。这正是错误消息告诉您的内容。这是修复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())