跳到主要内容

NamedPipeClient

搜索

结构体 NamedPipeClient 

源代码
pub struct NamedPipeClient { /* 私有字段 */ }
展开描述

Windows 命名管道客户端。

使用 ClientOptions::open 构造。

正确连接客户端涉及几个步骤。当通过 ClientOptions::open 连接时,它可能会出错,表示以下两种情况之一:

因此,正确实现的客户端如下所示:

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

源代码

pub unsafe fn from_raw_handle(handle: RawHandle) -> Result<Self>

从指定的原始句柄构造一个新的命名管道客户端。

此函数将取得所提供句柄的所有权,将关闭句柄的责任移交给返回的对象。

此函数同样是不安全的,因为当前返回的原语带有以下约定:它们是其包装的文件描述符的唯一所有者。使用此函数可能会意外违反该约定,从而在依赖该约定的代码中导致内存不安全。

§错误

如果在 Tokio 运行时 之外调用、在未启用 I/O 的运行时中调用,或发生任何操作系统特定的 I/O 错误,则返回错误。

源代码

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>

等待任何所请求的就绪状态。

此函数通常与 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<()>

等待管道变为可读。

此函数等价于 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<()>>

轮询读就绪状态。

如果管道当前未准备好读取数据,此方法将存储来自所提供 Context 中的 Waker 的克隆。当管道变为可读时,将在该 waker 上调用 Waker::wake

请注意,在多次调用 poll_read_readypoll_read 时,只有传递给最近一次调用的 Context 中的 Waker 会被调度以接收唤醒。(但是,poll_write_ready 保留了一个独立的第二个唤醒器。)

此函数用于通过 readable 创建和固定 future 不可行的情况。在可能的情况下,首选使用 readable,因为它支持同时从多个任务进行轮询。

§返回值

函数返回:

  • Poll::Pending if 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>

尝试从管道读取数据到提供的缓冲区,返回读取的字节数。

接收管道上任何待处理的数据,但不会等待新数据到达。成功时返回读取的字节数。由于 try_read() 是非阻塞的,缓冲区不必由异步任务存储,可以完全存在于栈上。

通常,readable()ready() 与此函数配对使用。

§返回值

如果成功读取数据,则返回 Ok(n),其中 n 是读取的字节数。如果 n0,则可能表示以下两种情况之一:

  1. The pipe’s read half is closed and will no longer yield data.
  2. 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>

尝试从管道读取数据到提供的多个缓冲区,返回读取的字节数。

按顺序复制数据以填充每个缓冲区,最后写入的缓冲区可能只被部分填充。此方法的行为等效于使用串联缓冲区对 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<()>

等待管道变为可写。

此函数等价于 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<()>>

轮询写就绪状态。

如果管道当前未准备好写入数据,此方法将存储来自所提供 Context 中的 Waker 的克隆。当管道变为可写时,将在该 waker 上调用 Waker::wake

请注意,在多次调用 poll_write_readypoll_write 时,只有传递给最近一次调用的 Context 中的 Waker 会被调度以接收唤醒。(但是,poll_read_ready 保留了一个独立的第二个唤醒器。)

此函数用于通过 writable 创建和固定 future 不可行的情况。在可能的情况下,首选使用 writable,因为它支持同时从多个任务进行轮询。

§返回值

函数返回:

  • Poll::Pending if 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>

尝试将缓冲区写入管道,返回写入的字节数。

该函数将尝试写入 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>

尝试将多个缓冲区写入管道,返回写入的字节数。

按顺序从每个缓冲区写入数据,最后读取的缓冲区可能只被部分使用。此方法的行为等效于使用串联缓冲区对 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>

尝试使用用户提供的 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>

使用用户提供的 I/O 操作从管道读取或写入数据。

会等待管道的就绪状态,当管道就绪时,会调用提供的闭包。闭包应通过手动调用适当的系统调用来尝试在管道上执行 I/O 操作。如果操作失败的原因是管道实际上尚未就绪,则闭包应返回 WouldBlock 错误。在这种情况下,会清除就绪标志并重新等待管道就绪。该循环将一直重复,直到闭包返回 Ok 或除 WouldBlock 之外的错误。

闭包仅在已对管道执行了 I/O 操作且因管道未就绪而失败时,才应返回 WouldBlock 错误。在其他任何情况下返回 WouldBlock 错误都会错误地清除就绪标志,可能导致管道行为异常。

闭包不应使用 Tokio NamedPipeClient 类型上定义的任何方法来执行 I/O 操作,因为这会干扰就绪标志,并可能导致管道行为异常。

此方法不应用于组合的就绪事件。闭包应当只执行一种 I/O 操作,因此不应需要多于一个的就绪状态。如果以组合的就绪事件调用,此方法可能会发生 panic 或永久休眠。

trait 实现§

源代码§

impl AsHandle for NamedPipeClient

源代码§

fn as_handle(&self) -> BorrowedHandle<'_>

Borrows the handle. 更多信息
源代码§

impl AsRawHandle for NamedPipeClient

源代码§

fn as_raw_handle(&self) -> RawHandle

Extracts the raw handle. 更多信息
源代码§

impl AsyncRead for NamedPipeClient

源代码§

fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>, ) -> Poll<Result<()>>

Attempts to read from the AsyncRead into buf. 更多信息
源代码§

impl AsyncWrite for NamedPipeClient

源代码§

fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll<Result<usize>>

Attempt to write bytes from buf into the object. 更多信息
源代码§

fn poll_write_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll<Result<usize>>

Like poll_write, except that it writes from a slice of buffers. 更多信息
源代码§

fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<()>>

Attempts to flush the object, ensuring that any buffered data reach their destination. 更多信息
源代码§

fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Initiates or attempts to shut down this writer, returning success when the I/O connection has completely shut down. 更多信息
源代码§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored implementation. 更多信息
源代码§

impl Debug for NamedPipeClient

源代码§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

使用给定的格式化器格式化此值。 更多信息

自动 trait 实现§

blanket 实现§

源代码§

impl<T> Any for T
where T: 'static + ?Sized,

源代码§

fn type_id(&self) -> TypeId

Gets the TypeId of self. 更多信息
源代码§

impl<T> Borrow<T> for T
where T: ?Sized,

源代码§

fn borrow(&self) -> &T

Immutably borrows from an owned value. 更多信息
源代码§

impl<T> BorrowMut<T> for T
where T: ?Sized,

源代码§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. 更多信息
源代码§

impl<T> From<T> for T

源代码§

fn from(t: T) -> T

原样返回参数。

源代码§

impl<T, U> Into<U> for T
where U: From<T>,

源代码§

fn into(self) -> U

调用 U::from(self)

也就是说,此转换是 From<T> for U 实现选择执行的操作。

源代码§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

源代码§

type Error = Infallible

转换出错时返回的类型。
源代码§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

执行转换。
源代码§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

源代码§

type Error = <U as TryFrom<T>>::Error

转换出错时返回的类型。
源代码§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

执行转换。