Отправка и получение сообщений параллельно не работает - PullRequest
0 голосов
/ 10 апреля 2019

У меня есть простой сервер / клиент asyncio tcp chat.Но есть проблема с, как мне кажется, отправкой сообщений.Вместо того, чтобы получать и отправлять сообщения параллельно, если у меня есть 2 или более клиентов, они получают другие сообщения только после того, как отправят свои.Как решить эту проблему?

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

1 Ответ

0 голосов
/ 10 апреля 2019

Основная проблема заключалась в том, что сопрограмма incoming_messages не работала в фоновом режиме. Вместо этого он был повторно вызван после того, как output_messages закончен.

Мне также пришлось внести другие изменения, чтобы запустить код на Python 3.6

  • запустить incoming_messages в фоновом режиме
  • list_of_users теперь список
  • без обработчика контекста для сервера
  • нет serve_forever

Попробуйте этот код:

Сервер

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

Клиент

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