简体   繁体   中英

Sending and receiving messages in parallel does not work

I have a simple asyncio tcp chat server/client. But there is an issue with, it seems to me, sending messages. Instead of receiving and sending messages in parallel, if I have 2 or more clients, they receive other messages only after they send theirs. How to solve this problem?

import asyncio


list_of_users = {}

async def handle_echo(reader, writer):
    name = await reader.read(1024)
    name.decode()
    print(name)

    addr = writer
    list_of_users[addr]

    while True:
        data = await reader.read(1024)
        message = data.decode()
        if not message:
            del list_of_users[addr]
            break
        msg(message)



def msg(message):
    for user in list_of_users:
        print('send message - ', message)
        user.write(message.encode())


async def main():
    server = await asyncio.start_server(
        handle_echo, '127.0.0.1', 8888)
    addr = server.sockets[0].getsockname()
    print(f'Serving on {addr}')
    async with server:
        await server.serve_forever()

asyncio.run(main())

import asyncio
from aioconsole import ainput


async def tcp_echo_client():
    reader, writer = await asyncio.open_connection('127.0.0.1', 8888)
    name = input('Enter your name: ')
    writer.write(name.encode())

    while True:
        await output_messages(writer)
        await incoming_messages(reader)


async def output_messages(writer):
    message = await ainput()
    writer.write(message.encode())


async def incoming_messages(reader):
    input_message = await reader.read(1024)
    print('print incoming message', input_message)


async def main():
    await tcp_echo_client()


asyncio.run(main())

The main issue was that the coroutine incoming_messages did not run in the background. Instead it was repeatedly called after output_messages finished.

I also had to make other adjustments to get the code running on Python 3.6

  • run incoming_messages in the background
  • list_of_users is now a list
  • no context handler for the server
  • no serve_forever

Try this code:

Server

import asyncio

list_of_users = []


async def handle_echo(reader, writer):
    name = await reader.read(1024)
    name.decode()
    print(name)

    addr = writer
    list_of_users.append(addr)

    while True:
        data = await reader.read(1024)
        message = data.decode()
        if not message:
            list_of_users.remove(addr)
            break
        msg(message)


def msg(message):
    for user in list_of_users:
        print('send message - ', message)
        user.write(message.encode())


async def main():
    server = await asyncio.start_server(
        handle_echo, '127.0.0.1', 8888)
    addr = server.sockets[0].getsockname()
    print(f'Serving on {addr}')
    await asyncio.sleep(3600)


asyncio.ensure_future(main())
loop = asyncio.get_event_loop()
loop.run_forever()

Client

import asyncio
from aioconsole import ainput


async def tcp_echo_client():
    reader, writer = await asyncio.open_connection('127.0.0.1', 8888)
    name = input('Enter your name: ')
    writer.write(name.encode())

    asyncio.ensure_future(incoming_messages(reader))
    while True:
        await output_messages(writer)


async def output_messages(writer):
    message = await ainput()
    writer.write(message.encode())


async def incoming_messages(reader):
    while True:
        input_message = await reader.read(1024)
        print('print incoming message', input_message)


async def main():
    await tcp_echo_client()


asyncio.get_event_loop().run_until_complete(main())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM