pub trait AsyncWrite {
// Required methods
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<Result<usize>>;
fn poll_flush(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Result<()>>;
fn poll_shutdown(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Result<()>>;
// Provided methods
fn poll_write_vectored(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &[IoSlice<'_>],
) -> Poll<Result<usize>> { ... }
fn is_write_vectored(&self) -> bool { ... }
}展开描述
异步写入字节。
此 trait 类似于 std::io::Write trait,但与异步任务系统集成。
特别地,poll_write 方法与 Write::write 不同,
当数据尚不可用时,它会自动将当前任务排入唤醒队列并立即返回,
而不是阻塞调用线程。
具体来说,这意味着 poll_write 函数将返回以下之一:
-
Poll::Ready(Ok(n))表示n个字节的数据已立即被写入。 -
Poll::Pending表示没有从提供的缓冲区写入数据。 I/O 对象当前不可写,但未来可能变为可写。 最重要的是,当前 future 的任务被安排在该对象可写时被唤醒。 这意味着与Future::poll类似, 当 I/O 对象再次可写时你将收到通知。 -
其它错误的
Poll::Ready(Err(e))是来自底层对象的标准 I/O 错误。
用于处理 AsyncWrite 值的工具方法由 AsyncWriteExt 提供。
大多数用户通过这些扩展方法与 AsyncWrite 类型交互,
这些扩展方法提供了诸如 write_all 和 flush 等易用的异步函数。
必需方法§
Sourcefn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<Result<usize>>
fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll<Result<usize>>
尝试将 buf 中的字节写入对象。
成功时,返回 Poll::Ready(Ok(num_bytes_written))。
如果成功,则必须保证 n <= buf.len()。
返回值为 0 通常表示底层对象已经无法再接受字节,
未来可能也无法再接受;或者提供的缓冲区为空。
如果对象尚未准备好写入,此方法返回 Poll::Pending,
并安排当前任务(通过 cx.waker())在该对象变为可写或被关闭时收到通知。
Sourcefn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>
尝试刷新对象,确保任何缓冲的数据都到达目的地。
成功时,返回 Poll::Ready(Ok(()))。
如果刷新不能立即完成,此方法返回 Poll::Pending,
并安排当前任务(通过 cx.waker())在该对象可以推进刷新时收到通知。
Sourcefn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>
启动或尝试关闭此写入器,当 I/O 连接已完全关闭时返回成功。
此方法旨在用于 I/O 连接的异步关闭。
例如,它适用于实现 TLS 连接的关闭,
或在代理连接上调用 TcpStream::shutdown。
协议有时需要刷新出最后的数据或执行优雅的关闭握手,
并根据需要读取/写入更多数据。
此方法就是供这些协议实现优雅关闭逻辑的钩子。
AsyncWrite trait 的实现者需要提供此 shutdown 方法。
包装类型通常只需将此调用代理给被包装的类型,
基础类型通常会在这里实现关闭逻辑或直接返回 Ok(().into())。
请注意,如果你包装了底层的 AsyncWrite,
对 shutdown 的调用意味着整个流都会被传递性地关闭。
在你的包装器的关闭逻辑执行完毕后,应当关闭底层的流。
调用 shutdown 隐含着调用 flush。
一旦此方法返回 Ready,就意味着在关闭之前已经成功执行了一次 flush。
也就是说,调用方无需在调用 shutdown 之前调用 flush。
可以依赖:通过调用 shutdown,所有挂起的缓冲数据都会被写出。
§Return value
此函数返回分类如下的 Poll<io::Result<()>>:
-
Poll::Ready(Ok(()))—— 表示连接已成功关闭, 现在可以安全地释放/丢弃/关闭与其相关的资源。 此方法意味着由于此方法当前任务不再接收任何通知, I/O 对象本身可能也无法再使用。 -
Poll::Pending—— 表示关闭已经启动,但目前尚未完成。 这可能意味着需要更多的 I/O 才能继续此关闭操作。 当前任务被安排在可以继续关闭操作时收到通知。 被唤醒后应再次调用此方法。 -
Poll::Ready(Err(e))—— 表示关闭过程中发生了致命错误, 说明关闭操作未成功完成。 这通常意味着 I/O 对象已经无法再使用。
§Errors
此函数可以通过 Err 返回上述普通 I/O 错误。
此外,此方法还可能使底层的 Write::write 方法不再可用(在未来返回错误)。
建议一旦调用了 shutdown,就不再调用 write 方法。
§Panics
如果不在 future 任务的上下文中调用此函数,它将 panic。
提供方法§
Sourcefn poll_write_vectored(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &[IoSlice<'_>],
) -> Poll<Result<usize>>
fn poll_write_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll<Result<usize>>
与 poll_write 类似,但它从一个缓冲区切片中写入数据。
数据按顺序从每个缓冲区复制,最后一个被读取的缓冲区可能仅被部分消费。
此方法必须表现得如同调用 write 来写入这些缓冲区拼接起来的数据一样。
默认实现会使用提供的第一个非空缓冲区调用 poll_write,
如果不存在非空缓冲区,则使用一个空缓冲区。
成功时,返回 Poll::Ready(Ok(num_bytes_written))。
如果对象尚未准备好写入,此方法返回 Poll::Pending,
并安排当前任务(通过 cx.waker())在该对象变为可写或被关闭时收到通知。
§Note
此方法应实现为单个“原子”写入操作。 如果已经部分写入了数据,那么返回错误或 pending 都是错误的。
Sourcefn is_write_vectored(&self) -> bool
fn is_write_vectored(&self) -> bool
判断此写入器是否具有高效的 poll_write_vectored 实现。
如果写入器没有覆盖默认的 poll_write_vectored 实现,
那么使用它的代码可能希望完全避免该方法,
将写入合并到单个缓冲区中以获得更高的性能。
默认实现返回 false。