import asyncio async def ping(reader: asyncio.StreamReader, writer: asyncio.StreamWriter): try: print('client connected') while not reader.at_eof(): data = await reader.readline() print('received data') writer.write(b'pong ' + data) await writer.drain() print('send pong') except asyncio.CancelledError: print('Connection cancelled') # never called finally: print('Connection closed!') # never called class Factory: def __init__(self, loop, callback): self.loop = loop self.callback = callback def __call__(self): reader = asyncio.StreamReader(loop=self.loop) return asyncio.StreamReaderProtocol(reader, self.callback, loop=loop) HOST = 'localhost' PORT = 9999 async def client(loop: asyncio.AbstractEventLoop): reader, writer = await asyncio.open_connection(HOST, PORT, loop=loop) print('connected to server') writer.write(b'hi!\n') await writer.drain() print('hi server!') data = await reader.readline() print('server answer ' + str(data, encoding='utf-8')) # writer.close() # print('closed') async def close_server(server): return await server.wait_close() if __name__ == '__main__': loop = asyncio.get_event_loop() server = loop.run_until_complete( loop.create_server(Factory(loop, ping), host=HOST, port=PORT) ) loop.run_until_complete(client(loop)) server.close() loop.run_until_complete(server.wait_closed()) print(asyncio.Task.all_tasks()) print(loop._ready)