Создание соединений с помощью python3 asyncio

Я пытаюсь подключиться к нескольким серверам одновременно. В настоящее время я использую loop.create_connection, но он зависает на первом не отвечающем сервере.

gsock = loop.create_connection(lambda: opensock(sid), server, port)
transport, protocol = loop.run_until_complete(gsock)

Я попытался использовать это, но это создало проблемы с используемым значением sid, а также с различными ошибками, такими как RuntimeError: Event loop is running и RuntimeError: Event loop stopped before Future completed. Кроме того, согласно моим переменным (которые были перепутаны), метод протокола connection_made() выполняется, когда transport, protocol = loop.run_until_complete(gsock) выдает исключение.

Я мало что понимаю в модуле asyncio, поэтому, пожалуйста, будьте максимально внимательны. Я не думаю, что мне нужны переменные чтения/записи, так как чтение должно выполняться автоматически и запускать метод data_received().

Благодарю вас.


person baudsmoke    schedule 27.05.2015    source источник


Ответы (1)


Вы можете подключиться ко многим серверам одновременно, запланировав все сопрограммы одновременно, а не используя loop.run_until_complete для создания каждого подключения по отдельности. Один из способов сделать это — использовать asyncio.gather для планирования их всех и дождаться завершения каждого:

import asyncio

# define opensock somewhere

@asyncio.coroutine
def connect_serv(server, port):
    try:
        transport, protocol = yield from loop.create_connection(lambda: opensock(sid), server, port)
    except Exception:
        print("Connection to {}:{} failed".format(server, port))

loop = asyncio.get_event_loop()
loop.run_until_complete(
    asyncio.gather(
      connect_serv('1.2.3.4', 3333),
      connect_serv('2.3.4.5', 5555),
      connect_serv('google.com', 80),
 ))
loop.run_forever()

Это запустит все три сопрограммы, перечисленные в вызове gather, одновременно, так что, если одна из них зависнет, другие не пострадают; они смогут продолжать свою работу, пока другое соединение зависает. Затем, если все они завершены, выполняется loop.run_forever(), что позволит вашей программе продолжать работу до тех пор, пока вы не остановите цикл или не завершите программу.

Упомянутые вами переменные reader/writer будут иметь значение только в том случае, если вы использовали asyncio.open_connection для подключения к серверам, а не create_connection. Он использует Stream API, который представляет собой API более высокого уровня, чем API на основе протокола/транспорта, который использует create_connection. Это действительно зависит от вас, чтобы решить, что вы предпочитаете использовать. Существуют примеры оба в asyncio документах, если вы хочу увидеть сравнение.

person dano    schedule 27.05.2015
comment
Спасибо большое! Попробую вашу технику. - person baudsmoke; 27.05.2015
comment
Мне все еще интересно, можно ли использовать run_until_complete(), пока выполняется run_forever(). Думаю, я попробую это после того, как перепишу. - person baudsmoke; 27.05.2015
comment
На самом деле это не рабочее решение, потому что сокеты не полностью активны (если только все подключения к серверу не будут выполнены своевременно). Программа зависает в ожидании одного из подключений к серверу. - person baudsmoke; 27.05.2015
comment
@baudsmoke Я не понимаю, что ты имеешь в виду. Какие сокеты не полностью активны? Что конкретно висит? Программа предназначена для блокировки вызова run_until_complete, возможно, навсегда, если один из вызовов connect_serv никогда не вернется. Однако вызовы connect_serv, которые не зависают, должны продолжать работать нормально. - person dano; 01.06.2015