Dmitriy Zverev
Dmitriy Zverev

Reputation: 21

Non-blocking websockets client using AIOHTTP

I'm trying to build a websocket live-chat client on Python using websockets from AIOHTTP. I'm having issues with msg = await ainput('> ') - this is blocking code. After i run this code, client blocked on this line until user enter some value. After value is entered displays one message from server and blocked on this line again.

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())

I tried to rewrite this code as two separate tasks, but I ran into a context manager problem. And client still 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())

What is the solution for non-blocking live-chat client?

Upvotes: 0

Views: 1962

Answers (1)

Dmitriy Zverev
Dmitriy Zverev

Reputation: 21

For non-blocking client need to create separate tasks for read and write. This works fine.

async def run(ws):
    async for msg in ws:
        if msg.type == WSMsgType.TEXT:
            print('Message received from server:', msg)


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


async def main():

    async with ClientSession().ws_connect('http://0.0.0.0:8080/ws') as ws:
        run_task = asyncio.create_task(run(ws))
        promt_task = asyncio.create_task(promt(ws))
        await asyncio.gather(promt_task, run_task)


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

Upvotes: 2

Related Questions