如何使用 asyncio UDP 客户端添加超时

how to add timeout with asyncio UDP client

我的代码是这样的,基本上就是照搬Python
中UDP Echo Client的示例代码 官方文档。

import asyncio
from asyncio import DatagramProtocol


class EchoClientProtocol(DatagramProtocol):
    def __init__(self, message, on_con_lost):
        self.message = message
        self.on_con_lost = on_con_lost
        self.transport = None

    def connection_made(self, transport):
        self.transport = transport
        print('Send:', self.message)
        self.transport.sendto(self.message.encode())

    def datagram_received(self, data, addr):
        print("Received:", data.decode())

        print("Close the socket")
        self.transport.close()

    def error_received(self, exc):
        print('Error received:', exc)

    def connection_lost(self, exc):
        print("Connection closed")
        self.on_con_lost.set_result(True)


async def main():

    loop = asyncio.get_running_loop()

    on_con_lost = loop.create_future()
    message = "Hello World!"
    transport, protocol = await loop.create_datagram_endpoint(
        lambda: EchoClientProtocol(message, on_con_lost),
        remote_addr=('127.0.0.1', 20001)
    )

    try:
        await on_con_lost
    finally:
        transport.close()


asyncio.run(main())

有效well.But 当服务不可用时,客户端将被阻止。我尝试添加 asyncio.wait_for 来修复它,但它不起作用。

transport, protocol = await asyncio.wait_for(loop.create_datagram_endpoint(
    lambda: EchoClientProtocol(message, on_con_lost),
    remote_addr=('127.0.0.1', 20001)
), 5)

我猜测可能是因为我不完全理解 on_con_lost 参数的这种用法,如何操作?

这是我认为正在发生的事情:

您正在启动数据报端点。 然后,您在断开连接的未来拥有启动器块。 为了触发断开连接的未来,必须调用 connection_lost 函数。 但是如果一开始就没有连接, connection_made 没有被调用,那么 future 就不会准备好。 您真正想要的是将超时添加到等待未来。 如果您收到超时过期异常,则关闭连接。 您当前代码的工作方式是启动端点,一旦超时,代码将继续等待断开连接的未来,现在无法准备就绪。