简体   繁体   中英

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

I'm writing a tcp client in python3.5 using asyncio After reading How to detect write failure in asyncio? that talk about the high-level streaming api, I've tried to implement using the low level 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()

As per the python documentation, I know write is non-blocking, and I would like the wait_all_data_have_been_written_or_throw to tell me if all data have been written or if something bad happened in the middle (like a connection lost, but I assume there's way more things that can go bad, and that the underlying socket already return exception about it?)

Does the standard library provide a way to do so ?

The question is mainly related to TCP sockets functionality, not asyncio implementation itself.

Let's look on the following code:

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

Successful send() call means the data was transferred into kernel space buffer for the socket, nothing more.

Data was not sent via wire, not received by peer and, obviously, not processed by received. Actual sending is performed asynchronously by Operation System Kernel, user code has no control over it.

What's why wait_all_data_have_been_written_or_throw() make not much sense: writing without an error doesn't assume receiving these data by peer but only successful moving from user-space buffer to kernel-space one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM