Tornado 方便的非阻塞套接字包装器
用于写入和读取非阻塞文件和套接字的实用程序类。
主要有:
BaseIOStream
:用于读写的通用接口。
IOStream
:使用非阻塞套接字实现 BaseIOStream。
SSLIOStream
:支持 SSL 的 IOStream 版本。
PipeIOStream
:基于管道的 IOStream 实现。
基本内容
class tornado.iostream.BaseIOStream(max_buffer_size: Optional[int] = None, read_chunk_size: Optional[int] = None, max_write_buffer_size: Optional[int] = None)
用于写入和读取非阻塞文件或套接字的实用程序类。
我们支持非阻塞 write()
和一系列 read_*()
方法。操作完成后,Awaitable
将解析为读取的数据(或 None
用于 write()
)。当流关闭时,所有未完成的 Awaitables
将使用 StreamClosedError
解决;BaseIOStream.set_close_callback
也可用于通知关闭的流。
当流因错误而关闭时,IOStream
的错误属性包含异常对象。
子类必须实现 fileno
、close_fd
、write_to_fd
、read_from_fd
和可选的 get_fd_error
。
BaseIOStream
构造函数。
参数:
max_buffer_size
– 要缓冲的最大传入数据量;默认为 100MB。
read_chunk_size
– 一次从底层传输读取的数据量;默认为 64KB。
max_write_buffer_size
– 输出到缓冲区的数据量;默认为无限制。
在 4.0 版更改: 添加 max_write_buffer_size
参数。将默认 read_chunk_size
更改为 64KB。
在 5.0 版中更改: io_loop
参数(自 4.1 版以来已弃用)已被删除。
主界面
BaseIOStream.write(data: Union[bytes, memoryview]) → Future[None]
将给定数据异步写入此流。
此方法返回一个 Future
,它在写入完成时解析(结果为 None
)。
data
参数可以是bytes
或memoryview
类型。
在 4.0 版更改: 如果没有给出回调,现在返回 Future
。
在 4.5 版更改: 添加了对 memoryview
参数的支持。
在 6.0 版更改: 回调参数已删除。 改用返回的 Future
。
BaseIOStream.read_bytes(num_bytes: int, partial: bool = False) → Awaitable[bytes]
异步读取多个字节。
如果 partial
为真,只要我们有任何要返回的字节,就会返回数据(但永远不会超过 num_bytes
)
在 4.0 版更改: 添加了部分参数。 回调参数现在是可选的,如果省略,将返回 Future
。
在 6.0 版更改: callback
和 streaming_callback
参数已被删除。 改用返回的 Future
(对于 streaming_callback
,partial=True
)。
BaseIOStream.read_into(buf: bytearray, partial: bool = False) → Awaitable[int]
异步读取多个字节。
buf
必须是读取数据的可写缓冲区。
如果 partial
为真,则在读取任何字节后立即运行回调。 否则,当 buf
完全被读取数据填充时运行。
5.0 版中的新功能。
在 6.0 版更改: 回调参数已删除。 改用返回的Future
。
BaseIOStream.read_until(delimiter: bytes, max_bytes: Optional[int] = None) → Awaitable[bytes]
异步读取,直到我们找到给定的分隔符。
结果包括读取的所有数据,包括分隔符。
如果 max_bytes
不是 None
,如果读取的字节数超过 max_bytes
并且找不到分隔符,则连接将被关闭。
在 4.0 版更改: 添加了 max_bytes
参数。 回调参数现在是可选的,如果省略,将返回 Future
。
在 6.0 版更改: 回调参数已删除。 改用返回的 Future
。
BaseIOStream.read_until_regex(regex: bytes, max_bytes: Optional[int] = None) → Awaitable[bytes]
异步读取,直到我们匹配给定的正则表达式。
结果包括与正则表达式匹配的数据以及它之前的任何内容。
如果 max_bytes
不是 None
,如果读取的字节数超过 max_bytes 并且不满足正则表达式,则连接将被关闭。
在 4.0 版更改: 添加了 max_bytes 参数。 回调参数现在是可选的,如果省略,将返回 Future。
在 6.0 版更改: 回调参数已删除。 改用返回的 Future。
BaseIOStream.read_until_close() → Awaitable[bytes]
从套接字异步读取所有数据,直到它关闭。
这将缓冲所有可用数据,直到达到 max_buffer_size
。 如果需要流量控制或取消,请使用带有 read_bytes(partial=True)
的循环。
在 4.0 版更改: 回调参数现在是可选的,如果省略,将返回 Future
。
在 6.0 版更改: callback
和 streaming_callback
参数已被删除。 改为使用返回的 Future
(以及对于 streaming_callback
的 read_bytes
和 partial=True
)。
BaseIOStream.close(exc_info: Union[None, bool, BaseException, Tuple[Optional[Type[BaseException]], Optional[BaseException], Optional[traceback]]] = False) → None
关闭这个Stream
如果 exc_info
为真,则将错误属性设置为 sys.exc_info
中的当前异常(或者如果 exc_info
是一个元组,则使用它而不是 sys.exc_info
)。
BaseIOStream.set_close_callback(callback: Optional[Callable[[], None]]) → None
当Stream关闭时调用给定的回调。
这对于使用 Future 接口的应用程序来说是不必要的; 当Stream关闭时,所有未完成的 Future 都将使用 StreamClosedError
解决。 但是,它仍然是一种有用的方式来表示流已关闭,而没有其他读取或写入正在进行。
与其他基于回调的接口不同,set_close_callback
在 Tornado 6.0 中没有被移除。
BaseIOStream.closed() → bool
如果Stream已关闭,则返回 True
BaseIOStream.reading() → bool
如果我们当前正在从Stream中读取,则返回 True
BaseIOStream.writing() → bool
如果我们当前正在写入Stream,则返回 True
。
BaseIOStream.set_nodelay(value: bool) → None
为此Stream设置无延迟标志。
默认情况下,写入 TCP Stream的数据可能会保留一段时间,以最有效地利用带宽(根据 Nagle 算法)。 无延迟标志要求尽快写入数据,即使这样做会消耗额外的带宽。
此标志当前仅针对基于 TCP 的 IOStream
定义。
子类的方法
BaseIOStream.fileno() → Union[int, tornado.ioloop._Selectable]
返回此Stream的文件描述符。
BaseIOStream.close_fd() → None
关闭此Stream的基础文件。
close_fd
由 BaseIOStream
调用,不应在其他地方调用; 其他用户应改为调用 close
。
BaseIOStream.write_to_fd(data: memoryview) → int
尝试将数据写入基础文件。
返回写入的字节数。
BaseIOStream.read_from_fd(buf: Union[bytearray, memoryview]) → Optional[int]
尝试从基础文件中读取。
最多读取 len(buf)
个字节,并将它们存储在缓冲区中。 返回读取的字节数。 如果没有要读取的内容(套接字返回 EWOULDBLOCK
或等效项),则返回 None
,在 EOF
上返回零。
在 5.0 版更改: 重新设计接口以获取缓冲区并返回多个字节而不是新分配的对象。
BaseIOStream.get_fd_error() → Optional[Exception]
返回有关基础文件上的任何错误的信息。
此方法在 IOLoop
发出文件描述符上的错误信号后调用,并且应返回异常(例如带有附加信息的 socket.error
,如果没有此类信息可用,则返回 None
。
实现
class tornado.iostream.IOStream(socket: socket.socket, *args, **kwargs)
基于套接字的 IOStream
实现。
此类支持来自 BaseIOStream
的读取和写入方法以及连接方法。
套接字参数可以是已连接的或未连接的。 对于服务器操作,套接字是调用 socket.accept
的结果。 对于客户端操作,套接字是使用 socket.socket
创建的,并且可以在将其传递给 IOStream
之前进行连接,也可以使用 IOStream.connect
进行连接。
一个使用此类的非常简单(且损坏)的 HTTP 客户端:
import tornado.ioloop
import tornado.iostream
import socket
async def main():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
stream = tornado.iostream.IOStream(s)
await stream.connect(("friendfeed.com", 80))
await stream.write(b"GET / HTTP/1.0\r\nHost: friendfeed.com\r\n\r\n")
header_data = await stream.read_until(b"\r\n\r\n")
headers = {}
for line in header_data.split(b"\r\n"):
parts = line.split(b":")
if len(parts) == 2:
headers[parts[0].strip()] = parts[1].strip()
body_data = await stream.read_bytes(int(headers[b"Content-Length"]))
print(body_data)
stream.close()
if __name__ == '__main__':
tornado.ioloop.IOLoop.current().run_sync(main)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
stream = tornado.iostream.IOStream(s)
stream.connect(("friendfeed.com", 80), send_request)
tornado.ioloop.IOLoop.current().start()
connect(address: Any, server_hostname: Optional[str] = None) → Future[_IOStreamType]
将套接字连接到远程地址而不阻塞。
仅当传递给构造函数的套接字先前未连接时才可以调用。 address
参数的格式与 socket.connect
的格式相同,用于传递给 IOStream
构造函数的套接字类型,例如 一个(ip,port)
元组。 此处接受主机名,但将同步解析并阻止 IOLoop
。 如果您有主机名而不是 IP 地址,则建议使用 TCPClient
类而不是直接调用此方法。 TCPClient
将进行异步 DNS 解析并同时处理 IPv4 和 IPv6。
如果指定了回调,则连接完成时将不带参数调用; 如果不是,则此方法返回一个 Future(成功连接后的结果将是Stream本身)。
在 SSL 模式下,server_hostname
参数将用于证书验证(除非在 ssl_options
中禁用)和 SNI
(如果支持;需要 Python 2.7.9+)。
请注意,在连接挂起时调用 IOStream.write
是安全的,在这种情况下,一旦连接准备好,数据就会被写入。 在连接套接字之前调用 IOStream
读取方法适用于某些平台,但不可移植。
在 4.0 版更改: 如果没有给出回调,则返回 Future
。
在 4.2 版更改:默认情况下验证 SSL 证书; 将 ssl_options=dict(cert_reqs=ssl.CERT_NONE)
或适当配置的 ssl.SSLContext
传递给 SSLIOStream
构造函数以禁用。
在 6.0 版更改: 回调参数已删除。 改用返回的 Future
。
start_tls(server_side: bool, ssl_options: Union[Dict[str, Any], ssl.SSLContext, None] = None, server_hostname: Optional[str] = None) → Awaitable[tornado.iostream.SSLIOStream]
将此IOStream
转换为SSLIOStream
。
这使得能够在清除文本模式下以清晰文本模式开头的协议,并在一些初始协商后切换到SSL(例如STARTTLS
扩展到SMTP
和IMAP
)。
如果在Stream
上有未完成的读取或写入,或者如果在IOStream
的缓冲区中存在任何数据(允许操作系统的套接字缓冲区中的数据),则无法使用此方法。这意味着它通常必须在阅读或写入最后一个清晰文本数据之后立即使用。在任何读取或写入之前,也可以立即使用它。
ssl_options
参数可以是ssl.slcontext
对象或ssl.wrap_socket
函数的关键字参数字典。除非在SSL_Options
中禁用,否则Server_Hostname
参数将用于证书验证。
此方法返回一个future
,其结果是新的SSLIOStream
。在调用此方法后,原始Stream
上的任何其他操作都未定义。
如果在此Stream
上定义了关闭回调,则将传输到新Stream
。
4.0版中的新增功能。
在4.2版中更改:默认情况下验证SSL证书; pass ssl_options = dict(cert_reqs = ssl.cert_none)
或适当配置的ssl.slcontext
禁用。
class tornado.iostream.SSLIOStream(*args, **kwargs)
用于写入和读取非阻塞 SSL 套接字的实用程序类。
如果传递给构造函数的套接字已经连接,则应使用以下内容进行包装:
ssl.wrap_socket(sock, do_handshake_on_connect=False, **kwargs)
在构造 SSLIOStream
之前。 当 IOStream.connect
完成时,未连接的套接字将被包装。
ssl_options
关键字参数可以是 ssl.SSLContext
对象或 ssl.wrap_socket
的关键字参数字典
wait_for_handshake() → Future[SSLIOStream]
等待初始 SSL 握手完成。
如果给定了回调,则在握手完成后将不带参数地调用它; 否则,此方法返回一个 Future
,它将在握手完成后解析为Stream
本身。
握手完成后,可以在 self.socket
上访问对等方的证书和 NPN/ALPN
选择等信息。
此方法旨在用于服务器端Stream
或使用 IOStream.start_tls
之后; 它不应该与 IOStream.connect
一起使用(它已经在等待握手完成)。 每个流只能调用一次。
4.2 版中的新功能。
在 6.0 版更改: 回调参数已删除。 改用返回的 Future
。
class tornado.iostream.PipeIOStream(fd: int, *args, **kwargs)
基于管道的 IOStream
实现。
构造函数采用整数文件描述符(例如 os.pipe
返回的描述符)而不是打开的文件对象。 管道通常是单向的,因此 PipeIOStream
可用于读取或写入,但不能同时用于两者。
PipeIOStream
仅在基于Unix的平台上可用。
例外
exception tornado.iostream.StreamBufferFullError
缓冲区已满时 IOStream
方法引发的异常。
exception tornado.iostream.StreamClosedError(real_error: Optional[BaseException] = None)
关闭 Stream
时 IOStream
方法引发的异常。
请注意,关闭回调计划在Stream
上的其他回调之后运行(以允许处理缓冲数据),因此您可能会在看到关闭回调之前看到此错误。
real_error
属性包含导致Stream
关闭的基础错误(如果有)。
在 4.3 版更改: 添加了 real_error
属性。
exception tornado.iostream.UnsatisfiableReadError
无法满足读取时引发异常。
由带有 max_bytes
参数的 read_until
和 read_until_regex
引发。
更多建议: