首页 > 解决方案 > 为什么 asyncio.StreamReader.read 返回没有阻塞线程?

问题描述

我试图运行这个异步示例https://docs.python.org/3.6/library/asyncio-stream.html?highlight=start_server#tcp-echo-server-using-streams

这条线让我感到困惑:

data = yield from reader.read(100) # data -> b'Hello World!'

客户端向服务器发送字符串'Hello World!'Bytearray长度小于 100。

coroutine read(n=-1) 最多读取 n 个字节。如果未提供 n 或设置为 -1,则读取直到 EOF 并返回所有读取字节。

如果收到 EOF 并且内部缓冲区为空,则返回一个空字节对象。

这个方法是协程。

我没有EOF在客户端发送,那么为什么该read功能没有被阻止?这是否意味着Bytearray包含EOFafter string.encode

标签: pythonpython-3.6python-asyncio

解决方案


我没有在客户端发送EOF,那么为什么读取功能没有被阻止?

因为收到了一些数据,并read提供了它。您明确引用的文档说read(n)最多n 个字节”。这是一个特性:如果read(n)仅在完整的 n 个字节可用时返回,它将在回显服务器中引入缓冲区膨胀,在读入全部量之前不会回显任何内容。有了这样的语义,唯一的方法就是有一个回显没有缓冲区引起的延迟的服务器将使用 逐字节读取数据read(1),这将是非常低效的。

回显服务器使用的预期含义read(n)是“一旦数据可用就给我数据,但一次不超过n个字节”。必须提供限制不是因为它必然有意义,而只是为了防止流氓对等方通过发送大量数据来淹没您的内存。

请注意,通过这样的read()指定,很容易定义另一个函数来读取数据,直到确切的数量可用;其实这样的方法就StreamReader已经存在了:readexactly.

这是否意味着 Bytearray 在 string.encode 之后包含 EOF?

从不“包含 EOF”返回的字节对象(与 bytearray 对象不同),因为EOF不是字符read,它是带外信号的条件。在StreamReaderAPI 中,EOF 条件通过read返回一个空字节对象来指示。


推荐阅读