Структура Sender
pub struct Sender { /* private fields */ }
net.Конец Unix-канала для записи.
Его можно создать из FIFO-файла с помощью OpenOptions::open_sender.
Открытие именованного канала для записи состоит из нескольких шагов. Вызов OpenOptions::open_sender может завершиться ошибкой, указывающей на разные причины:
-
io::ErrorKind::NotFound— по указанному пути нет файла. -
io::ErrorKind::InvalidInput— файл существует, но не является FIFO. -
ENXIO— файл является FIFO, но ни один процесс не открыл его для чтения. Подождите немного и повторите попытку. - Другие ошибки ОС, не связанные непосредственно с открытием FIFO-файлов.
Открытие Sender из FIFO-файла должно выглядеть так:
use tokio::net::unix::pipe;
use tokio::time::{self, Duration};
const FIFO_NAME: &str = "path/to/a/fifo";
// Wait for a reader to open the file.
let tx = loop {
match pipe::OpenOptions::new().open_sender(FIFO_NAME) {
Ok(tx) => break tx,
Err(e) if e.raw_os_error() == Some(libc::ENXIO) => {},
Err(e) => return Err(e.into()),
}
time::sleep(Duration::from_millis(50)).await;
};В Linux можно создать Sender без ожидания в цикле с паузами. Для этого именованный канал открывают в режиме чтения и записи с помощью OpenOptions::read_write. Таким образом, Sender может одновременно иметь открытыми конец для записи и конец для чтения; последний позволяет открыть FIFO без ошибки ENXIO, поскольку канал также открыт для чтения.
Sender нельзя использовать для чтения из канала, поэтому на практике доступ на чтение используется только при открытии FIFO. Однако использование Sender в режиме чтения и записи может привести к потере данных, поскольку система отбросит записанные данные, как только будут закрыты все концы канала. Чтобы избежать потери данных, необходимо убедиться, что конец для чтения был открыт до закрытия Sender.
Обратите внимание: использование режима чтения и записи для FIFO-файлов не определено стандартом POSIX и гарантированно работает только в Linux.
use tokio::io::AsyncWriteExt;
use tokio::net::unix::pipe;
const FIFO_NAME: &str = "path/to/a/fifo";
let mut tx = pipe::OpenOptions::new()
.read_write(true)
.open_sender(FIFO_NAME)?;
// Asynchronously write to the pipe before a reader.
tx.write_all(b"hello world").await?;
Реализации
impl Sender
pub fn from_file(file: File) -> Result<Sender>
Создаёт новый Sender из File.
Эта функция предназначена для создания канала из File, представляющего специальный FIFO-файл. Она проверит, является ли файл каналом и доступна ли запись, установит неблокирующий режим и выполнит преобразование.
Ошибки
Функция завершается ошибкой io::ErrorKind::InvalidInput, если файл не является каналом или не имеет доступа на запись. Также функция завершается ошибкой при возникновении любой стандартной ошибки ОС.
Паники
Функция вызывает панику, если её вызывают вне среды выполнения с включённым вводом-выводом.
Среда выполнения обычно устанавливается неявно, когда эта функция вызывается из future, выполняемой средой выполнения tokio. В противном случае среду выполнения можно установить явно с помощью функции Runtime::enter.
pub fn from_owned_fd(owned_fd: OwnedFd) -> Result<Sender>
Создаёт новый Sender из OwnedFd.
Эта функция предназначена для создания канала из OwnedFd, представляющего анонимный канал или специальный FIFO-файл. Она проверит, является ли файловый дескриптор каналом и доступна ли запись, установит неблокирующий режим и выполнит преобразование.
Ошибки
Функция завершается ошибкой io::ErrorKind::InvalidInput, если файловый дескриптор не является каналом или не имеет доступа на запись. Также функция завершается ошибкой при возникновении любой стандартной ошибки ОС.
Паники
Функция вызывает панику, если её вызывают вне среды выполнения с включённым вводом-выводом.
Среда выполнения обычно устанавливается неявно, когда эта функция вызывается из future, выполняемой средой выполнения tokio. В противном случае среду выполнения можно установить явно с помощью функции Runtime::enter.
pub fn from_file_unchecked(file: File) -> Result<Sender>
Создаёт новый Sender из File без проверки свойств канала.
Эта функция предназначена для создания канала из File, представляющего специальный FIFO-файл. При преобразовании ничего не предполагается о базовом файле; пользователь должен самостоятельно убедиться, что он открыт для записи, представляет собой канал и установлен в неблокирующий режим.
Примеры
use tokio::net::unix::pipe;
use std::fs::OpenOptions;
use std::os::unix::fs::{FileTypeExt, OpenOptionsExt};
const FIFO_NAME: &str = "path/to/a/fifo";
let file = OpenOptions::new()
.write(true)
.custom_flags(libc::O_NONBLOCK)
.open(FIFO_NAME)?;
if file.metadata()?.file_type().is_fifo() {
let tx = pipe::Sender::from_file_unchecked(file)?;
/* use the Sender */
}Паники
Функция вызывает панику, если её вызывают вне среды выполнения с включённым вводом-выводом.
Среда выполнения обычно устанавливается неявно, когда эта функция вызывается из future, выполняемой средой выполнения tokio. В противном случае среду выполнения можно установить явно с помощью функции Runtime::enter.
pub fn from_owned_fd_unchecked(owned_fd: OwnedFd) -> Result<Sender>
Создаёт новый Sender из OwnedFd без проверки свойств канала.
Эта функция предназначена для создания канала из OwnedFd, представляющего анонимный канал или специальный FIFO-файл. При преобразовании ничего не предполагается о базовом канале; пользователь должен самостоятельно убедиться, что файловый дескриптор представляет пишущий конец канала и что канал установлен в неблокирующий режим.
Паники
Функция вызывает панику, если её вызывают вне среды выполнения с включённым вводом-выводом.
Среда выполнения обычно устанавливается неявно, когда эта функция вызывается из future, выполняемой средой выполнения tokio. В противном случае среду выполнения можно установить явно с помощью функции Runtime::enter.
pub async fn ready(&self, interest: Interest) -> Result<Ready>
Ожидает наступления любого из запрошенных состояний готовности.
Эту функцию можно использовать вместо writable(), чтобы проверить, содержит ли возвращённый набор готовности события Ready::WRITABLE и Ready::WRITE_CLOSED.
Функция может завершиться, даже если канал не готов. Это ложноположительный результат, и попытка выполнить операцию вернёт io::ErrorKind::WouldBlock. Функция также может вернуть пустой набор Ready, поэтому всегда проверяйте возвращённое значение и, если запрошенные состояния не установлены, при необходимости ожидайте снова.
Безопасность при отмене
Этот метод безопасен при отмене. После наступления события готовности метод будет сразу же возвращать результат, пока событие готовности не будет обработано попыткой записи, завершившейся ошибкой WouldBlock или Poll::Pending.
pub async fn writable(&self) -> Result<()>
Ожидает, пока канал не станет доступен для записи.
Эта функция эквивалентна ready(Interest::WRITABLE) и обычно используется вместе с try_write().
Примеры
use tokio::net::unix::pipe;
use std::io;
#[tokio::main]
async fn main() -> io::Result<()> {
// Open a writing end of a fifo
let tx = pipe::OpenOptions::new().open_sender("path/to/a/fifo")?;
loop {
// Wait for the pipe to be writable
tx.writable().await?;
// Try to write data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match tx.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<()>>
Проверяет готовность к записи.
Если канал в данный момент не готов к записи, этот метод сохранит копию Waker из переданного Context. Когда канал будет готов к записи, для waker будет вызван Waker::wake.
Обратите внимание: при нескольких вызовах poll_write_ready или poll_write пробуждение запланировано только для Waker из Context, переданного при последнем вызове.
Эта функция предназначена для случаев, когда создание и закрепление future с помощью writable невозможно. Если это возможно, предпочтительно использовать writable, так как этот вариант поддерживает опрос сразу из нескольких задач.
Возвращаемое значение
Функция возвращает:
-
Poll::Pending, если канал не готов к записи. -
Poll::Ready(Ok(())), если канал готов к записи. -
Poll::Ready(Err(e)), если произошла ошибка.
Ошибки
Эта функция может завершиться любой стандартной ошибкой ввода-вывода, кроме WouldBlock.
pub fn try_write(&self, buf: &[u8]) -> Result<usize>
Пытается записать буфер в канал и возвращает количество записанных байтов.
Функция попытается записать всё содержимое buf, но может быть записана только часть буфера. Если длина buf не превышает PIPE_BUF (константа ОС, равная 4096 в Linux), запись гарантированно будет атомарной: либо будет записано всё содержимое buf, либо этот метод завершится ошибкой WouldBlock. Если buf больше PIPE_BUF, такой гарантии нет.
Эта функция обычно используется вместе с writable.
Возвращаемое значение
Если данные успешно записаны, возвращается Ok(n), где n — количество записанных байтов. Если канал не готов к записи данных, возвращается Err(io::ErrorKind::WouldBlock).
Примечания
Чтобы избежать ненужных системных вызовов, попытка записи выполняется только в том случае, если ОС сообщила Tokio, что канал стал доступен для записи. Поэтому try_write() может завершиться ошибкой WouldBlock, если Tokio ещё не получил от ОС уведомление о том, что канал стал доступен для записи.
Примеры
use tokio::net::unix::pipe;
use std::io;
#[tokio::main]
async fn main() -> io::Result<()> {
// Open a writing end of a fifo
let tx = pipe::OpenOptions::new().open_sender("path/to/a/fifo")?;
loop {
// Wait for the pipe to be writable
tx.writable().await?;
// Try to write data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match tx.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() с объединёнными буферами.
Если суммарная длина буферов не превышает PIPE_BUF (константа ОС, в Linux — 4096), запись гарантированно выполняется атомарно: либо будет записано всё содержимое буферов, либо этот метод завершится ошибкой WouldBlock. Если суммарная длина буферов превышает PIPE_BUF, такой гарантии нет.
Обычно эта функция используется вместе с writable.
Возвращаемое значение
Если данные успешно записаны, возвращается Ok(n), где n — количество записанных байтов. Если канал не готов к записи данных, возвращается Err(io::ErrorKind::WouldBlock).
Примечания
Чтобы избежать ненужных системных вызовов, запись будет выполняться только в том случае, если ОС сообщила Tokio, что канал стал доступен для записи. Поэтому вызов try_write_vectored() может завершиться ошибкой WouldBlock, если Tokio ещё не получил от ОС уведомление о готовности канала к записи.
Примеры
use tokio::net::unix::pipe;
use std::io;
#[tokio::main]
async fn main() -> io::Result<()> {
// Open a writing end of a fifo
let tx = pipe::OpenOptions::new().open_sender("path/to/a/fifo")?;
let bufs = [io::IoSlice::new(b"hello "), io::IoSlice::new(b"world")];
loop {
// Wait for the pipe to be writable
tx.writable().await?;
// Try to write data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match tx.try_write_vectored(&bufs) {
Ok(n) => {
break;
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
Ok(())
}pub fn try_io<R>(&self, f: impl FnOnce() -> Result<R>) -> Result<R>
Пытается выполнить запись в сокет с помощью предоставленной пользователем операции ввода-вывода.
Если сокет готов, вызывается предоставленная функция-замыкание. Она должна попытаться выполнить операцию ввода-вывода с сокетом, вручную вызвав соответствующий системный вызов. Если операция завершается неудачей, поскольку сокет фактически не готов, функция-замыкание должна вернуть ошибку WouldBlock, после чего флаг готовности будет сброшен. Затем try_io вернёт результат функции-замыкания.
Если сокет не готов, функция-замыкание не вызывается, а возвращается ошибка WouldBlock.
Функция-замыкание должна возвращать ошибку WouldBlock только в том случае, если она выполнила операцию ввода-вывода с сокетом, завершившуюся неудачей из-за его неготовности. Возврат ошибки WouldBlock в любой другой ситуации приведёт к неправильному сбросу флага готовности, что может вызвать некорректную работу сокета.
Функция-замыкание не должна выполнять операцию ввода-вывода с помощью методов, определённых для типа Tokio pipe::Sender, поскольку это нарушит работу флага готовности и может вызвать некорректную работу сокета.
Обычно эта функция используется вместе с writable() или ready().
pub fn into_blocking_fd(self) -> Result<OwnedFd>
Преобразует канал в OwnedFd в блокирующем режиме.
Эта функция удалит данный конец канала из цикла обработки событий, включит для него блокирующий режим и выполнит преобразование.
pub fn into_nonblocking_fd(self) -> Result<OwnedFd>
Преобразует канал в OwnedFd в неблокирующем режиме.
Эта функция удалит данный конец канала из цикла обработки событий и выполнит преобразование. Возвращённый файловый дескриптор будет работать в неблокирующем режиме.
Реализации трейтов
impl AsFd for Sender
fn as_fd(&self) -> BorrowedFd<'_>
impl AsyncWrite for Sender
fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll<Result<usize>>
buf в объект. Подробнее
fn poll_write_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll<Result<usize>>
poll_write, но записывает данные из среза буферов. Подробнее
fn is_write_vectored(&self) -> bool
poll_write_vectored. Подробнее
Автоматические реализации трейтов
impl !Freeze for Sender
impl RefUnwindSafe for Sender
impl Send for Sender
impl Sync for Sender
impl Unpin for Sender
impl UnsafeUnpin for Sender
impl UnwindSafe for Sender
Обобщённые реализации
impl<W> AsyncWriteExt for Wwhere W: AsyncWrite + ?Sized,
fn write<'a>(&'a mut self, src: &'a [u8]) -> Write<'a, Self>where Self: Unpin,
io-util.fn write_vectored<'a, 'b>( &'a mut self, bufs: &'a [IoSlice<'b>], ) -> WriteVectored<'a, 'b, Self>where Self: Unpin,
io-util.fn write_buf<'a, B>(&'a mut self, src: &'a mut B) -> WriteBuf<'a, Self, B>
io-util.fn write_all_buf<'a, B>( &'a mut self, src: &'a mut B, ) -> WriteAllBuf<'a, Self, B>
io-util.fn write_all<'a>(&'a mut self, src: &'a [u8]) -> WriteAll<'a, Self>where Self: Unpin,
io-util.fn write_u16(&mut self, n: u16) -> WriteU16<&mut Self>where Self: Unpin,
io-util.fn write_i16(&mut self, n: i16) -> WriteI16<&mut Self>where Self: Unpin,
io-util.fn write_u32(&mut self, n: u32) -> WriteU32<&mut Self>where Self: Unpin,
io-util.fn write_i32(&mut self, n: i32) -> WriteI32<&mut Self>where Self: Unpin,
io-util.fn write_u64(&mut self, n: u64) -> WriteU64<&mut Self>where Self: Unpin,
io-util.fn write_i64(&mut self, n: i64) -> WriteI64<&mut Self>where Self: Unpin,
io-util.fn write_u128(&mut self, n: u128) -> WriteU128<&mut Self>where Self: Unpin,
io-util.fn write_i128(&mut self, n: i128) -> WriteI128<&mut Self>where Self: Unpin,
io-util.fn write_f32(&mut self, n: f32) -> WriteF32<&mut Self>where Self: Unpin,
io-util.fn write_f64(&mut self, n: f64) -> WriteF64<&mut Self>where Self: Unpin,
io-util.fn write_u16_le(&mut self, n: u16) -> WriteU16Le<&mut Self>where Self: Unpin,
io-util.fn write_i16_le(&mut self, n: i16) -> WriteI16Le<&mut Self>where Self: Unpin,
io-util.fn write_u32_le(&mut self, n: u32) -> WriteU32Le<&mut Self>where Self: Unpin,
io-util.fn write_i32_le(&mut self, n: i32) -> WriteI32Le<&mut Self>where Self: Unpin,
io-util.fn write_u64_le(&mut self, n: u64) -> WriteU64Le<&mut Self>where Self: Unpin,
io-util.fn write_i64_le(&mut self, n: i64) -> WriteI64Le<&mut Self>where Self: Unpin,
io-util.fn write_u128_le(&mut self, n: u128) -> WriteU128Le<&mut Self>where Self: Unpin,
io-util.fn write_i128_le(&mut self, n: i128) -> WriteI128Le<&mut Self>where Self: Unpin,
io-util.fn write_f32_le(&mut self, n: f32) -> WriteF32Le<&mut Self>where Self: Unpin,
io-util.fn write_f64_le(&mut self, n: f64) -> WriteF64Le<&mut Self>where Self: Unpin,
io-util.impl<T> BorrowMut<T> for Twhere T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
impl<T> Instrument for T
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
impl<T> WithSubscriber for T
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ
Subscriber к этому типу и возвращает обёртку WithDispatch. Подробнее
MIT License
Copyright © Tokio Contributors
https://docs.rs/tokio/1.53.1/tokio/net/unix/pipe/struct.Sender.html