D
D
Dmitry2020-07-29 10:29:41
Python
Dmitry, 2020-07-29 10:29:41

How to implement a non-blocking websocket client on AIOHTTP?

Hey!
There is the following code that implements a client to connect to a websocket.

async def client_run():

    async with ClientSession().ws_connect('http://0.0.0.0:8080/ws') as ws:

        await ws.send_str('Hello!')
        async for msg in ws:
            if msg.type == WSMsgType.TEXT:
                if msg.data == 'close cmd':
                    await ws.close()
                    break
                else:
                    await aprint('Message received from server:', msg)
                    msg = await ainput('> ')
                    await ws.send_str(msg)
            elif msg.type == WSMsgType.ERROR:
                break

if __name__ == '__main__':
    print('Type "exit" to quit')
    loop = asyncio.get_event_loop()
    loop.run_until_complete(client_run())


The problem is that the line msg = await ainput('> ')is blocking.
How can I implement a client on AIOHTTP so that it works in non-blocking mode? Those. the client displays the data that comes from the server in live mode (live chat).
There is a similar, but working as it should, asyncio code.
import websockets
import asyncio

class WebSocketClient():

    def __init__(self):
        pass

    async def connect(self):
        self.connection = await websockets.client.connect('ws://0.0.0.0:8080/ws')
        return self.connection

    async def sendMessage(self, connection):
        while True:
            message = await ainput('> ')
            await self.connection.send(message)

    async def receiveMessage(self, connection):
        while True:
            message = await self.connection.recv()
            print('Message received from server: ' + str(message))

async def main(client, connection):
    await asyncio.gather(
        client.receiveMessage(connection),
        client.sendMessage(connection)
    )


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    client = WebSocketClient()
    connection = loop.run_until_complete(client.connect())
    loop.run_until_complete(main(client, connection))


update#1:
Tried such implementation, but it is also blocked.

async def run_client(ws):
    await ws.send_str('Hello!')
    async for msg in ws:
        if msg.type == WSMsgType.TEXT:
            if msg.data == 'close cmd':
                await ws.close()
                break
            else:
                await aprint('Message received from server:', msg)

async def promt(ws):
    while True:
        msg = await ainput('Your text here: ')
        await ws.send_str(msg)


async def main():
    async with ClientSession().ws_connect('http://0.0.0.0:8080/ws') as ws:
        await asyncio.gather(
            run_client(ws),
            promt(ws)
        )


if __name__ == '__main__':
    print('Type "exit" to quit')
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dr. Bacon, 2020-07-29
@Zveridze

As in the second example, write a separate loop for ainput and run a separate task.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question