Python 3.6中Websocket客户端接收消息出现问题

15

我正在尝试使用Websockets 4.0 API中的websockets包,在Python上构建websocket客户端。

我使用了这种方式,而不是示例代码,因为我想创建一个websocket客户端类对象,并将其用作网关。

我的问题在于客户端侧的监听器方法(receiveMessage),它在执行时引发了ConnectionClose异常。我认为可能是循环有问题。

这是我尝试构建的简单WebSocket客户端:

import websockets

class WebSocketClient():

    def __init__(self):
        pass

    async def connect(self):
        '''
            Connecting to webSocket server

            websockets.client.connect returns a WebSocketClientProtocol, which is used to send and receive messages
        '''
        self.connection = await websockets.client.connect('ws://127.0.0.1:8765')
        if self.connection.open:
            print('Connection stablished. Client correcly connected')
            # Send greeting
            await self.sendMessage('Hey server, this is webSocket client')
            # Enable listener
            await self.receiveMessage()


    async def sendMessage(self, message):
        '''
            Sending message to webSocket server
        '''
        await self.connection.send(message)

    async def receiveMessage(self):
        '''
            Receiving all server messages and handling them
        '''
        while True:
            message = await self.connection.recv()
            print('Received message from server: ' + str(message))

这是主要内容:

'''
    Main file
'''

import asyncio
from webSocketClient import WebSocketClient

if __name__ == '__main__':
    # Creating client object
    client = WebSocketClient()
    loop = asyncio.get_event_loop()
    loop.run_until_complete(client.connect())
    loop.run_forever()
    loop.close()

为了测试消息监听器,服务器在建立连接时会向客户端发送两条消息。

客户端正确连接到服务器并发送问候语。但是,当客户端接收到这两个消息时,它会引发一个代码为1000(无原因)的ConnectionClosed异常

如果我在receiveMessage客户端方法中删除循环,客户端将不会引发任何异常,但它只会接收一条消息,所以我想需要一个循环来保持监听器活动状态,但我不知道确切的位置或方式。

有什么解决办法吗?

谢谢。

编辑:我意识到客户端在接收到所有待处理消息后关闭连接(并终止循环)。但是,我希望客户端保持活动状态以监听未来的消息。

此外,我尝试添加另一个功能,其任务是向服务器发送“心跳”,但客户端仍然关闭连接。

1个回答

24

最后,根据这个帖子的回答,我这样修改了我的客户端和主文件:

WebSocket 客户端:

import websockets
import asyncio

class WebSocketClient():

    def __init__(self):
        pass

    async def connect(self):
        '''
            Connecting to webSocket server

            websockets.client.connect returns a WebSocketClientProtocol, which is used to send and receive messages
        '''
        self.connection = await websockets.client.connect('ws://127.0.0.1:8765')
        if self.connection.open:
            print('Connection stablished. Client correcly connected')
            # Send greeting
            await self.sendMessage('Hey server, this is webSocket client')
            return self.connection


    async def sendMessage(self, message):
        '''
            Sending message to webSocket server
        '''
        await self.connection.send(message)

    async def receiveMessage(self, connection):
        '''
            Receiving all server messages and handling them
        '''
        while True:
            try:
                message = await connection.recv()
                print('Received message from server: ' + str(message))
            except websockets.exceptions.ConnectionClosed:
                print('Connection with server closed')
                break

    async def heartbeat(self, connection):
        '''
        Sending heartbeat to server every 5 seconds
        Ping - pong messages to verify connection is alive
        '''
        while True:
            try:
                await connection.send('ping')
                await asyncio.sleep(5)
            except websockets.exceptions.ConnectionClosed:
                print('Connection with server closed')
                break

主要:

import asyncio
from webSocketClient import WebSocketClient

if __name__ == '__main__':
    # Creating client object
    client = WebSocketClient()
    loop = asyncio.get_event_loop()
    # Start connection and get client connection protocol
    connection = loop.run_until_complete(client.connect())
    # Start listener and heartbeat 
    tasks = [
        asyncio.ensure_future(client.heartbeat(connection)),
        asyncio.ensure_future(client.receiveMessage(connection)),
    ]

    loop.run_until_complete(asyncio.wait(tasks))

现在,客户端保持连接并监听来自服务器的所有消息,并每5秒向服务器发送'ping'消息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接