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

时间:2018-02-04 16:58:48

标签: python python-3.x python-asyncio

我使用asyncio在python3.5中编写tcp客户端 在阅读了关于高级流媒体API的How to detect write failure in asyncio?后,我尝试使用低级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告诉我所有数据是否已写入或中间是否发生了不良事件(如一个连接丢失了,但是我假设有更多的东西可以变坏,并且底层套接字已经返回异常了吗?)

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

1 个答案:

答案 0 :(得分:1)

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

让我们看一下以下代码:

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

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

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

为什么wait_all_data_have_been_written_or_throw()没有多大意义:没有错误写入并不假设通过对等方接收这些数据,但只是成功地从用户空间缓冲区移动到内核空间缓冲区。< / p>