pub struct NamedPipeClient { /* 私有字段 */ }展开描述
Windows 命名管道客户端。
使用 ClientOptions::open 构造。
正确连接客户端涉及几个步骤。当通过 ClientOptions::open 连接时,它可能会出错,表示以下两种情况之一:
std::io::ErrorKind::NotFound- There is no server available.ERROR_PIPE_BUSY- There is a server available, but it is busy. Sleep for a while and try again.
因此,正确实现的客户端如下所示:
use std::time::Duration;
use tokio::net::windows::named_pipe::ClientOptions;
use tokio::time;
use windows_sys::Win32::Foundation::ERROR_PIPE_BUSY;
const PIPE_NAME: &str = r"\\.\pipe\named-pipe-idiomatic-client";
let client = loop {
match ClientOptions::new().open(PIPE_NAME) {
Ok(client) => break client,
Err(e) if e.raw_os_error() == Some(ERROR_PIPE_BUSY as i32) => (),
Err(e) => return Err(e),
}
time::sleep(Duration::from_millis(50)).await;
};
/* use the connected client */实现§
源代码§impl NamedPipeClient
impl NamedPipeClient
源代码pub unsafe fn from_raw_handle(handle: RawHandle) -> Result<Self>
pub unsafe fn from_raw_handle(handle: RawHandle) -> Result<Self>
源代码pub fn info(&self) -> Result<PipeInfo>
pub fn info(&self) -> Result<PipeInfo>
检索与客户端关联的命名管道的信息。
use tokio::net::windows::named_pipe::{ClientOptions, PipeEnd, PipeMode};
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-client-info";
let client = ClientOptions::new()
.open(PIPE_NAME)?;
let client_info = client.info()?;
assert_eq!(client_info.end, PipeEnd::Client);
assert_eq!(client_info.mode, PipeMode::Message);
assert_eq!(client_info.max_instances, 5);源代码pub async fn ready(&self, interest: Interest) -> Result<Ready>
pub async fn ready(&self, interest: Interest) -> Result<Ready>
等待任何所请求的就绪状态。
此函数通常与 try_read() 或 try_write() 配对使用。它可用于在单个任务上同时对同一管道进行读/写,而无需拆分管道。
该函数可能在管道尚未就绪时完成。这是一种误报,尝试进行操作将返回 io::ErrorKind::WouldBlock。该函数也可能返回空的 Ready 集合,因此应始终检查返回值,如果请求的状态未设置,可能需要再次等待。
§示例
在同一任务上并发地对管道进行读写,而无需拆分。
use tokio::io::Interest;
use tokio::net::windows::named_pipe;
use std::error::Error;
use std::io;
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-client-ready";
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let client = named_pipe::ClientOptions::new().open(PIPE_NAME)?;
loop {
let ready = client.ready(Interest::READABLE | Interest::WRITABLE).await?;
if ready.is_readable() {
let mut data = vec![0; 1024];
// 尝试读取数据,这仍可能因 `WouldBlock` 而失败
// 如果就绪事件是误报。
match client.try_read(&mut data) {
Ok(n) => {
println!("read {} bytes", n);
}
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
if ready.is_writable() {
// 尝试写入数据,这仍可能因 `WouldBlock` 而失败
// 如果就绪事件是误报。
match client.try_write(b"hello world") {
Ok(n) => {
println!("write {} bytes", n);
}
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
}
}源代码pub async fn readable(&self) -> Result<()>
pub async fn readable(&self) -> Result<()>
等待管道变为可读。
此函数等价于 ready(Interest::READABLE),通常与 try_read() 配对使用。
§示例
use tokio::net::windows::named_pipe;
use std::error::Error;
use std::io;
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-client-readable";
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let client = named_pipe::ClientOptions::new().open(PIPE_NAME)?;
let mut msg = vec![0; 1024];
loop {
// Wait for the pipe to be readable
client.readable().await?;
// Try to read data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match client.try_read(&mut msg) {
Ok(n) => {
msg.truncate(n);
break;
}
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
println!("GOT = {:?}", msg);
Ok(())
}源代码pub fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<Result<()>>
pub fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<Result<()>>
轮询读就绪状态。
如果管道当前未准备好读取数据,此方法将存储来自所提供 Context 中的 Waker 的克隆。当管道变为可读时,将在该 waker 上调用 Waker::wake。
请注意,在多次调用 poll_read_ready 或 poll_read 时,只有传递给最近一次调用的 Context 中的 Waker 会被调度以接收唤醒。(但是,poll_write_ready 保留了一个独立的第二个唤醒器。)
此函数用于通过 readable 创建和固定 future 不可行的情况。在可能的情况下,首选使用 readable,因为它支持同时从多个任务进行轮询。
§返回值
函数返回:
Poll::Pendingif the pipe is not ready for reading.Poll::Ready(Ok(()))if the pipe is ready for reading.Poll::Ready(Err(e))if an error is encountered.
§错误
此函数可能遇到除 WouldBlock 之外的任何标准 I/O 错误。
源代码pub fn try_read(&self, buf: &mut [u8]) -> Result<usize>
pub fn try_read(&self, buf: &mut [u8]) -> Result<usize>
尝试从管道读取数据到提供的缓冲区,返回读取的字节数。
接收管道上任何待处理的数据,但不会等待新数据到达。成功时返回读取的字节数。由于 try_read() 是非阻塞的,缓冲区不必由异步任务存储,可以完全存在于栈上。
通常,readable() 或 ready() 与此函数配对使用。
§返回值
如果成功读取数据,则返回 Ok(n),其中 n 是读取的字节数。如果 n 为 0,则可能表示以下两种情况之一:
- The pipe’s read half is closed and will no longer yield data.
- The specified buffer was 0 bytes in length.
如果管道未准备好读取数据,则返回 Err(io::ErrorKind::WouldBlock)。
§示例
use tokio::net::windows::named_pipe;
use std::error::Error;
use std::io;
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-client-try-read";
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let client = named_pipe::ClientOptions::new().open(PIPE_NAME)?;
loop {
// Wait for the pipe to be readable
client.readable().await?;
// Creating the buffer **after** the `await` prevents it from
// being stored in the async task.
let mut buf = [0; 4096];
// Try to read data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match client.try_read(&mut buf) {
Ok(0) => break,
Ok(n) => {
println!("read {} bytes", n);
}
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
Ok(())
}源代码pub fn try_read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>
pub fn try_read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>
尝试从管道读取数据到提供的多个缓冲区,返回读取的字节数。
按顺序复制数据以填充每个缓冲区,最后写入的缓冲区可能只被部分填充。此方法的行为等效于使用串联缓冲区对 try_read() 进行单次调用。
接收管道上任何待处理的数据,但不会等待新数据到达。成功时返回读取的字节数。由于 try_read_vectored() 是非阻塞的,缓冲区不必由异步任务存储,可以完全存在于栈上。
通常,readable() 或 ready() 与此函数配对使用。
§返回值
如果成功读取数据,则返回 Ok(n),其中 n 是读取的字节数。Ok(0) 表示管道的读半部分已关闭,将不再产生数据。如果管道未准备好读取数据,则返回 Err(io::ErrorKind::WouldBlock)。
§示例
use tokio::net::windows::named_pipe;
use std::error::Error;
use std::io::{self, IoSliceMut};
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-client-try-read-vectored";
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let client = named_pipe::ClientOptions::new().open(PIPE_NAME)?;
loop {
// Wait for the pipe to be readable
client.readable().await?;
// Creating the buffer **after** the `await` prevents it from
// being stored in the async task.
let mut buf_a = [0; 512];
let mut buf_b = [0; 1024];
let mut bufs = [
IoSliceMut::new(&mut buf_a),
IoSliceMut::new(&mut buf_b),
];
// Try to read data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match client.try_read_vectored(&mut bufs) {
Ok(0) => break,
Ok(n) => {
println!("read {} bytes", n);
}
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
Ok(())
}源代码pub async fn writable(&self) -> Result<()>
pub async fn writable(&self) -> Result<()>
等待管道变为可写。
此函数等价于 ready(Interest::WRITABLE),通常与 try_write() 配对使用。
§示例
use tokio::net::windows::named_pipe;
use std::error::Error;
use std::io;
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-client-writable";
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let client = named_pipe::ClientOptions::new().open(PIPE_NAME)?;
loop {
// Wait for the pipe to be writable
client.writable().await?;
// Try to write data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match client.try_write(b"hello world") {
Ok(n) => {
break;
}
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
Ok(())
}源代码pub fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Result<()>>
pub fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Result<()>>
轮询写就绪状态。
如果管道当前未准备好写入数据,此方法将存储来自所提供 Context 中的 Waker 的克隆。当管道变为可写时,将在该 waker 上调用 Waker::wake。
请注意,在多次调用 poll_write_ready 或 poll_write 时,只有传递给最近一次调用的 Context 中的 Waker 会被调度以接收唤醒。(但是,poll_read_ready 保留了一个独立的第二个唤醒器。)
此函数用于通过 writable 创建和固定 future 不可行的情况。在可能的情况下,首选使用 writable,因为它支持同时从多个任务进行轮询。
§返回值
函数返回:
Poll::Pendingif the pipe is not ready for writing.Poll::Ready(Ok(()))if the pipe is ready for writing.Poll::Ready(Err(e))if an error is encountered.
§错误
此函数可能遇到除 WouldBlock 之外的任何标准 I/O 错误。
源代码pub fn try_write(&self, buf: &[u8]) -> Result<usize>
pub fn try_write(&self, buf: &[u8]) -> Result<usize>
尝试将缓冲区写入管道,返回写入的字节数。
该函数将尝试写入 buf 的全部内容,但缓冲区可能只有部分被写入。
此函数通常与 writable() 配对使用。
§返回值
如果成功写入数据,则返回 Ok(n),其中 n 是写入的字节数。如果管道未准备好写入数据,则返回 Err(io::ErrorKind::WouldBlock)。
§示例
use tokio::net::windows::named_pipe;
use std::error::Error;
use std::io;
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-client-try-write";
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let client = named_pipe::ClientOptions::new().open(PIPE_NAME)?;
loop {
// Wait for the pipe to be writable
client.writable().await?;
// Try to write data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match client.try_write(b"hello world") {
Ok(n) => {
break;
}
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
Ok(())
}源代码pub fn try_write_vectored(&self, buf: &[IoSlice<'_>]) -> Result<usize>
pub fn try_write_vectored(&self, buf: &[IoSlice<'_>]) -> Result<usize>
尝试将多个缓冲区写入管道,返回写入的字节数。
按顺序从每个缓冲区写入数据,最后读取的缓冲区可能只被部分使用。此方法的行为等效于使用串联缓冲区对 try_write() 进行单次调用。
此函数通常与 writable() 配对使用。
§返回值
如果成功写入数据,则返回 Ok(n),其中 n 是写入的字节数。如果管道未准备好写入数据,则返回 Err(io::ErrorKind::WouldBlock)。
§示例
use tokio::net::windows::named_pipe;
use std::error::Error;
use std::io;
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-client-try-write-vectored";
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let client = named_pipe::ClientOptions::new().open(PIPE_NAME)?;
let bufs = [io::IoSlice::new(b"hello "), io::IoSlice::new(b"world")];
loop {
// Wait for the pipe to be writable
client.writable().await?;
// Try to write data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match client.try_write_vectored(&bufs) {
Ok(n) => {
break;
}
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
Ok(())
}源代码pub fn try_io<R>(
&self,
interest: Interest,
f: impl FnOnce() -> Result<R>,
) -> Result<R>
pub fn try_io<R>( &self, interest: Interest, f: impl FnOnce() -> Result<R>, ) -> Result<R>
尝试使用用户提供的 I/O 操作从管道读取或写入数据。
如果管道已就绪,则调用提供的闭包。闭包应通过手动调用适当的系统调用来尝试在管道上执行 I/O 操作。如果操作失败的原因是管道实际上尚未就绪,则闭包应返回 WouldBlock 错误,同时会清除就绪标志。闭包的返回值随后由 try_io 返回。
如果管道未就绪,则不会调用闭包,并返回 WouldBlock 错误。
闭包仅在已对管道执行了 I/O 操作且因管道未就绪而失败时,才应返回 WouldBlock 错误。在其他任何情况下返回 WouldBlock 错误都会错误地清除就绪标志,可能导致管道行为异常。
闭包不应使用 Tokio NamedPipeClient 类型上定义的任何方法来执行 I/O 操作,因为这会干扰就绪标志,并可能导致管道行为异常。
此方法不应用于组合的就绪事件。闭包应当只执行一种 I/O 操作,因此不应需要多于一个的就绪状态。如果以组合的就绪事件调用,此方法可能会发生 panic 或永久休眠。
通常,readable()、writable() 或 ready() 与此函数一起使用。
源代码pub async fn async_io<R>(
&self,
interest: Interest,
f: impl FnMut() -> Result<R>,
) -> Result<R>
pub async fn async_io<R>( &self, interest: Interest, f: impl FnMut() -> Result<R>, ) -> Result<R>
使用用户提供的 I/O 操作从管道读取或写入数据。
会等待管道的就绪状态,当管道就绪时,会调用提供的闭包。闭包应通过手动调用适当的系统调用来尝试在管道上执行 I/O 操作。如果操作失败的原因是管道实际上尚未就绪,则闭包应返回 WouldBlock 错误。在这种情况下,会清除就绪标志并重新等待管道就绪。该循环将一直重复,直到闭包返回 Ok 或除 WouldBlock 之外的错误。
闭包仅在已对管道执行了 I/O 操作且因管道未就绪而失败时,才应返回 WouldBlock 错误。在其他任何情况下返回 WouldBlock 错误都会错误地清除就绪标志,可能导致管道行为异常。
闭包不应使用 Tokio NamedPipeClient 类型上定义的任何方法来执行 I/O 操作,因为这会干扰就绪标志,并可能导致管道行为异常。
此方法不应用于组合的就绪事件。闭包应当只执行一种 I/O 操作,因此不应需要多于一个的就绪状态。如果以组合的就绪事件调用,此方法可能会发生 panic 或永久休眠。
trait 实现§
源代码§impl AsHandle for NamedPipeClient
impl AsHandle for NamedPipeClient
源代码§fn as_handle(&self) -> BorrowedHandle<'_>
fn as_handle(&self) -> BorrowedHandle<'_>
源代码§impl AsRawHandle for NamedPipeClient
impl AsRawHandle for NamedPipeClient
源代码§fn as_raw_handle(&self) -> RawHandle
fn as_raw_handle(&self) -> RawHandle
源代码§impl AsyncRead for NamedPipeClient
impl AsyncRead for NamedPipeClient
源代码§impl AsyncWrite for NamedPipeClient
impl AsyncWrite for NamedPipeClient
源代码§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 into the object. 更多信息源代码§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, except that it writes from a slice of buffers. 更多信息源代码§fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<()>>
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<()>>
源代码§fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>
源代码§fn is_write_vectored(&self) -> bool
fn is_write_vectored(&self) -> bool
poll_write_vectored
implementation. 更多信息