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 的任务会被调度以获得 unpark 通知。这意味着与Future::poll类似,当 I/O 对象再次可写时,你将收到通知。 -
Poll::Ready(Err(e))表示其他错误,这些是来自底层对象的标准 I/O 错误。
用于处理 AsyncWrite 值的实用工具由 AsyncWriteExt 提供。大多数用户将通过这些扩展方法与 AsyncWrite 类型进行交互,这些方法提供了符合人体工程学的异步函数,例如 write_all 和 flush。
必需方法§
源代码fn 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())在对象变为可写或被关闭时接收通知。
源代码fn 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())在对象能够推进刷新时收到通知。
源代码fn 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,就意味着在关闭发生之前已成功执行了刷新。也就是说,调用者无需在调用 shutdown 之前调用 flush。他们可以相信通过调用 shutdown,任何挂起的已缓冲数据都将被写出。
§返回值
此函数返回 Poll<io::Result<()>>,分类如下:
-
Poll::Ready(Ok(()))- 表示连接已成功关闭,现在可以安全地释放/丢弃/关闭与其关联的资源。此方法意味着当前任务将不再收到由此方法导致的任何通知,并且 I/O 对象本身很可能不再可用。 -
Poll::Pending- 表示关闭已启动但目前无法完成。这可能意味着需要更多 I/O 才能继续此关闭操作。当前任务被调度为在其他条件允许继续关闭操作时收到通知。唤醒时应再次调用此方法。 -
Poll::Ready(Err(e))- 表示关闭过程中发生了致命错误,表明关闭操作未成功完成。这通常意味着 I/O 对象不再可用。
§错误
此函数可以通过 Err 返回正常的 I/O 错误,如上所述。此外,此方法还可能导致底层的 Write::write 方法不再可用(例如,将来会返回错误)。建议一旦调用了 shutdown,就不再调用 write 方法。
§恐慌
如果未在 future 任务的上下文中调用,此函数将发生 panic。
提供方法§
源代码fn 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())在对象变为可写或被关闭时接收通知。
§注意
这应实现为单个“原子”写入操作。如果已部分写入了任何数据,则返回错误或 pending 是错误的。
源代码fn is_write_vectored(&self) -> bool
fn is_write_vectored(&self) -> bool
确定此写入器是否具有高效的 poll_write_vectored 实现。
如果写入器未覆盖默认的 poll_write_vectored 实现,则使用它的代码可能希望完全避免该方法,并将写入合并到单个缓冲区中以获得更高的性能。
默认实现返回 false。