python3.5: asyncio,如何等待 "transport.write(data)" 完成或 return 错误?

python3.5: asyncio, How to wait for "transport.write(data)" to finish or to return an error?

我正在 python3.5 使用 asyncio 编写一个 tcp 客户端 在阅读了关于高级流 api 的 之后,我尝试使用低级 protocol api.

来实现
class _ClientProtocol(asyncio.Protocol):
    def connection_made(self, transport):
        self.transport = transport

class Client:
    def __init__(self, loop=None):
        self.protocol = _ClientProtocol()

        if loop is None:
            loop = asyncio.get_event_loop()
        self.loop = loop
        loop.run_until_complete(self._connect())

    async def _connect(self):
        await self.loop.create_connection(
            lambda: self.protocol,
            '127.0.0.1',
            8080,
        )
        # based on https://vorpus.org/blog/some-thoughts-on-asynchronous-api-design-in-a-post-asyncawait-world/#bug-3-closing-time
        self.protocol.transport.set_write_buffer_limits(0)

    def write(self, data):
        self.protocol.transport.write(data)

    def wait_all_data_have_been_written_or_throw():
        pass

client = Client()
client.write(b"some bytes")
client.wait_all_data_have_been_written_or_throw()

根据 python 文档,我知道 write 是非阻塞的,我希望 wait_all_data_have_been_written_or_throw 告诉我是否所有数据都已写入或是否有错误发生在中间(就像连接丢失,但我认为还有更多事情会变坏,并且底层套接字已经 return 关于它的异常?)

标准库是否提供这样做的方法?

问题主要与 TCP 套接字功能有关,而不是 asyncio 实现本身。

我们来看下面的代码:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send(b'data')

成功的send()调用意味着数据被传输到内核space套接字缓冲区,仅此而已。

数据不是通过线路发送的,没有被对等方接收,显然,没有被接收方处理。 实际发送是由操作系统内核异步执行的,用户代码无法控制它。

为什么 wait_all_data_have_been_written_or_throw() 没有多大意义:没有错误的写入并不假定对等方接收到这些数据,而只是成功地从 user-space 缓冲区移动到 kernel-space 一个.