Мне не хватает понимания того, как работают Python asyncio и протоколы.
Документация, которая представляется актуальной:
class asyncio.Protocol
Protocol.eof_received()
конечный автомат показывает соответствующие переходы
AbstractEventLoop.run_until_complete(future)
Пример кода, который является клиентом echo tcp:
import asyncio
class EchoClientProtocol(asyncio.Protocol):
def __init__(self, message, loop):
self.message = message.encode()
def connection_made(self, transport):
self.transport = transport
self.write_data()
def data_received(self, data):
print('Data received: {!r}',len(data))
self.write_data()
def eof_received(self):
print("eof")
return True
def write_data(self):
print("write")
self.transport.write(self.message)
def connection_lost(self, exc):
print('The server closed the connection')
print('Stop the event loop')
loop = asyncio.get_event_loop()
message = 'Hello World!'
coro = loop.create_connection(lambda: EchoClientProtocol(message, loop),
'127.0.0.1', 5676)
loop.run_until_complete(coro)
print("done")
Вывод на эхо-сервере при обработке:
write
Data received: {!r} 12
write
done
Насколько я понимаю, это должно работать, пока соединение не будет закрыто.
От: Обратные вызовы соединения
connection_made () и connection_lost () вызываются ровно один раз для каждого успешного соединения. Все остальные обратные вызовы будут вызываться между этими двумя методами, что упрощает управление ресурсами в реализации протокола.
и из конечного автомата:
start
-> connection_made
[-> data_received]*
[-> eof_received]?
-> connection_lost
-> end
Но функция EchoClientProtocol.connection_lost
никогда не вызывается и
loop.run_until_complete(coro)
завершается до завершения протокола.
Вопрос:
Как получить сопрограмму / будущее, которая оборачивает протокол таким образом, что сопрограмма завершается, когда достигается конечное состояние протокола и loop.run_until_complete возвращает такое событие.