【问题标题】:Why asyncio.StreamReader.read return didn't block the thread?为什么 asyncio.StreamReader.read 返回没有阻塞线程?
【发布时间】:2019-11-05 08:06:11
【问题描述】:

我尝试运行这个 asyncio 示例 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 功能没有被阻止? 这是否意味着Bytearraystring.encode 之后包含EOF

【问题讨论】:

  • 你检查returnyield之间的区别了吗?
  • 对不起,return这个词,我的意思是read函数执行的返回值(该值来自read函数内部的yield)。
  • 我不太明白你的回答,如果可以,请重新表述。无论如何,我的评论是建议yieldreturn 之间存在差异,这可能是您混淆的根源。另外,如果 Bytearray 小于 100,你为什么期望它返回更多呢?那不是你的EOF吗?
  • @MikeMajara 我希望服务器不会收到任何东西,因为 Bytearray 假设不包含 EOF 并且长度小于 100。服务器的会话将被阻止,直到它收到指定的长度.

标签: python python-3.6 python-asyncio


【解决方案1】:

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

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    • 2021-08-29
    • 2021-11-12
    • 2020-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多