首页 > 解决方案 > 连接丢失后如何销毁异步服务器上的协议实例?

问题描述

我在 Python 3.7 上有异步服务器。对于每个连接,asyncio 都会创建一个new EchoServerProtocol()对象。服务器收到第一个数据包后,关闭连接,但EchoServerProtocol()对象仍保留在内存中。你能告诉我如何正确删除它吗?我知道在 asyncio 的某个地方有指向它的链接。

服务器.py

import asyncio

class EchoServerProtocol(asyncio.Protocol):

    def __init__(self):
        self.__loop = asyncio.get_event_loop()

    def connection_made(self, transport):
        self.__loop.call_later(5, self.check_connection)
        print('Connection made')
        self.transport = transport

    def connection_lost(self, exc):
        print('Connection lost')

    def data_received(self, data):
        message = data.decode()
        print('Data received: {!r}'.format(message))

        print('Send: {!r}'.format(message))
        self.transport.write(data)

        print('Close the client socket')
        self.transport.close()

    def check_connection(self):
        print('check connection here')
        self.__loop.call_later(5, self.check_connection)

async def main():
    loop = asyncio.get_running_loop()

    server = await loop.create_server(
        lambda: EchoServerProtocol(),
        '127.0.0.1', 8888)

    async with server:
        await server.serve_forever()


asyncio.run(main())

客户端.py

import asyncio


class EchoClientProtocol(asyncio.Protocol):
    def __init__(self, message, on_con_lost, loop):
        self.message = message
        self.loop = loop
        self.on_con_lost = on_con_lost

    def connection_made(self, transport):
        transport.write(self.message.encode())
        print('Data sent: {!r}'.format(self.message))

    def data_received(self, data):
        print('Data received: {!r}'.format(data.decode()))

    def connection_lost(self, exc):
        print('The server closed the connection')
        self.on_con_lost.set_result(True)


async def main():
    # Get a reference to the event loop as we plan to use
    # low-level APIs.
    loop = asyncio.get_running_loop()

    on_con_lost = loop.create_future()
    message = 'Hello World!'

    transport, protocol = await loop.create_connection(
        lambda: EchoClientProtocol(message, on_con_lost, loop),
        '127.0.0.1', 8888)

    # Wait until the protocol signals that the connection
    # is lost and close the transport.
    try:
        await on_con_lost
    finally:
        transport.close()

输出:

Connection made
Data received: 'Hello World!'
Send: 'Hello World!'
Close the client socket
Connection lost
check connection here
check connection here
check connection here
check connection here
check connection here
check connection here
check connection here
check connection here

标签: pythonpython-asyncio

解决方案


user4815162342 是对的。感谢您的回复。我的愚蠢错误。

如果你想有一个监控任务,你应该让它成为一个协程,并在连接丢失时取消它。例如:

至于 check_connection 方法,我只是更改了代码并添加了del处理程序以确保正在删除对象。

def check_connection(self):
    print('check connection here')
    if not self.transport.is_closing():
        self.__loop.call_later(5, self.check_connection)

def __del__(self):
    print("destroy protocol")

推荐阅读