我在Python 3.7上安装了asynsio服务器。
对于每个连接,asyncio创建一个new EchoServerProtocol()
对象。收到第一个数据包后,服务器关闭连接,但是EchoServerProtocol()
对象保留在内存中。您能告诉我如何正确删除它吗?我了解到asyncio中的某处有链接。
server.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())
client.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
答案 0 :(得分:0)
服务器收到第一个数据包后,将关闭连接,但
EchoServerProtocol()
对象仍保留在内存中。
看看您的代码,是check_connection
将对象保留在内存中。具体来说,check_connection
的末尾说:
self.__loop.call_later(5, self.check_connection)
这表示:“ 5秒钟后,在check_connection
上调用self
”。 self
是不再使用的协议这一事实无关紧要-事件循环在5秒钟后被告知要调用一个函数,它将做到这一点。
如果您要执行监视任务,则应将其设为协程,并在连接断开时取消。例如:
class EchoServerProtocol(asyncio.Protocol):
def connection_made(self, transport):
loop = asyncio.get_event_loop()
self._checker = loop.create_task(self.check_connection())
print('Connection made')
self.transport = transport
def connection_lost(self, exc):
print('Connection lost')
self._checker.cancel()
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()
async def check_connection(self):
while True:
print('check connection here')
await asyncio.sleep(5)
答案 1 :(得分:0)
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")