Spec-Zone.ru › Tokio

Модуль io

Трейты, вспомогательные средства и определения типов для асинхронного ввода-вывода.

Этот модуль — асинхронная версия std::io. В основном в нём определены два трейта: AsyncRead и AsyncWrite, представляющие собой асинхронные версии трейтов Read и Write из стандартной библиотеки.

AsyncRead и AsyncWrite

Подобно трейтам Read и Write из стандартной библиотеки, AsyncRead и AsyncWrite предоставляют наиболее общий интерфейс для чтения и записи данных. Однако, в отличие от трейтов стандартной библиотеки, они являются асинхронными — это означает, что чтение из типа tokio::io или запись в него передаст управление планировщику Tokio, если ввод-вывод не готов, вместо того чтобы блокировать выполнение. Это позволяет запускать другие задачи, пока выполняются операции ввода-вывода.

Ещё одно отличие состоит в том, что AsyncRead и AsyncWrite содержат только основные методы, необходимые для асинхронного чтения и записи. Вспомогательные методы определены в трейтах-расширениях AsyncReadExt и AsyncWriteExt. Эти трейты автоматически реализуются для всех значений, реализующих соответственно AsyncRead и AsyncWrite.

Конечным пользователям редко приходится напрямую взаимодействовать с AsyncRead и AsyncWrite. Вместо этого они используют асинхронные функции, определённые в трейтах-расширениях. Ожидается, что авторы библиотек будут реализовывать AsyncRead и AsyncWrite, чтобы предоставлять типы, работающие как потоки байтов.

Несмотря на эти различия, трейты Tokio AsyncRead и AsyncWrite можно использовать почти так же, как Read и Write из стандартной библиотеки. Большинство типов стандартной библиотеки, реализующих Read и Write, имеют асинхронные аналоги в tokio, реализующие AsyncRead и AsyncWrite, например File и TcpStream.

Например, в документации стандартной библиотеки Read вводится с помощью примера чтения байтов из std::fs::File. То же самое можно сделать с помощью tokio::fs::File:

use tokio::io::{self, AsyncReadExt};
use tokio::fs::File;

#[tokio::main]
async fn main() -> io::Result<()> {
    let mut f = File::open("foo.txt").await?;
    let mut buffer = [0; 10];

    // read up to 10 bytes
    let n = f.read(&mut buffer).await?;

    println!("The bytes: {:?}", &buffer[..n]);
    Ok(())
}

Буферизованные средства чтения и записи

Интерфейсы на основе байтов неудобны и могут быть неэффективными, поскольку нам пришлось бы почти постоянно обращаться к операционной системе. Для решения этой проблемы std::io поддерживает буферизованные средства чтения и записи, и tokio::io тоже.

Tokio предоставляет асинхронную версию трейта std::io::BufRead — AsyncBufRead, а также асинхронные структуры BufReader и BufWriter, оборачивающие средства чтения и записи. Эти обёртки используют буфер, уменьшая количество вызовов и предоставляя более удобные методы для доступа именно к нужным данным.

Например, BufReader работает с трейтом AsyncBufRead, добавляя дополнительные методы для любого асинхронного средства чтения:

use tokio::io::{self, BufReader, AsyncBufReadExt};
use tokio::fs::File;

#[tokio::main]
async fn main() -> io::Result<()> {
    let f = File::open("foo.txt").await?;
    let mut reader = BufReader::new(f);
    let mut buffer = String::new();

    // read a line into buffer
    reader.read_line(&mut buffer).await?;

    println!("{}", buffer);
    Ok(())
}

BufWriter не добавляет новых способов записи — он лишь буферизует каждый вызов write. Однако, чтобы гарантировать запись всех буферизованных данных, необходимо вызвать метод сброса буфера у BufWriter.

use tokio::io::{self, BufWriter, AsyncWriteExt};
use tokio::fs::File;

#[tokio::main]
async fn main() -> io::Result<()> {
    let f = File::create("foo.txt").await?;
    {
        let mut writer = BufWriter::new(f);

        // Write a byte to the buffer.
        writer.write(&[42u8]).await?;

        // Flush the buffer before it goes out of scope.
        writer.flush().await?;

    } // Unless flushed or shut down, the contents of the buffer is discarded on drop.

    Ok(())
}

Реализация AsyncRead и AsyncWrite

Поскольку это трейты, мы можем реализовать AsyncRead и AsyncWrite и для собственных типов. Обратите внимание, что эти трейты следует реализовывать только для неблокирующих типов ввода-вывода, интегрированных с системой типов futures. Иными словами, эти типы никогда не должны блокировать поток; вместо этого текущая задача получает уведомление, когда ресурс ввода-вывода готов.

Преобразование в Stream/Sink и обратно

Часто бывает удобно инкапсулировать чтение и запись байтов в Stream или Sink данных.

Tokio предоставляет в крейте tokio-util простые обёртки для преобразования AsyncRead в Stream и обратно. См. ReaderStream и StreamReader.

Также доступны вспомогательные трейты, абстрагирующие асинхронную буферизацию, необходимую для создания собственных адаптеров кодирования и декодирования байтов в структурированные данные и обратно. Они позволяют преобразовать объект, реализующий AsyncRead/AsyncWrite, в Stream/Sink. См. Decoder и Encoder в модуле tokio-util::codec.

Стандартный ввод и вывод

Tokio предоставляет асинхронные API для стандартных потоков ввода, вывода и ошибок. Эти API очень похожи на предоставляемые std, но также реализуют AsyncRead и AsyncWrite.

Обратите внимание, что API стандартных потоков ввода-вывода необходимо использовать в контексте среды выполнения Tokio, поскольку для работы им нужны специфичные для Tokio функции. Вызов этих функций вне среды выполнения Tokio вызовет панику.

Реэкспорты std

Кроме того, Error, ErrorKind, Result и SeekFrom реэкспортируются из std::io для удобства использования.

Реэкспорты

pub use std::io::Error;
pub use std::io::ErrorKind;
pub use std::io::Result;
pub use std::io::SeekFrom;

Модули

bsdFreeBSD и только net
Типы ввода-вывода, специфичные для BSD.
unixUnix и только net
Асинхронные структуры ввода-вывода, специфичные для Unix-подобных операционных систем.

Структуры

BufReaderТолько io-util
Структура BufReader добавляет буферизацию любому средству чтения.
BufStreamТолько io-util
Оборачивает тип, реализующий AsyncWrite и AsyncRead, и буферизует его ввод и вывод.
BufWriterТолько io-util
Оборачивает средство записи и буферизует его вывод.
ChainТолько io-util
Поток для метода chain.
DuplexStreamТолько io-util
Двунаправленный канал для чтения и записи байтов в памяти.
EmptyТолько io-util
Empty игнорирует любые данные, записанные через AsyncWrite, и всегда остаётся пустым (возвращает ноль байтов) при чтении через AsyncRead.
InterestТолько net или tokio_unstable, Linux, fs, io-uring и rt
Интерес к событию готовности.
JoinТолько io-util
Объединяет два значения, реализующих AsyncRead и AsyncWrite, в один дескриптор.
LinesТолько io-util
Читает строки из AsyncBufRead.
ReadBuf
Обёртка над буфером байтов, который заполняется и инициализируется постепенно.
ReadHalfТолько io-util
Читаемая половина значения, возвращённого функцией split.
ReadyТолько net или tokio_unstable, Linux, fs, io-uring и rt
Описывает состояние готовности ресурса ввода-вывода.
RepeatТолько io-util
Асинхронное средство чтения, которое снова и снова выдаёт один байт…
SimplexStreamТолько io-util
Однонаправленный канал для чтения и записи байтов в памяти.
SinkТолько io-util
Асинхронное средство записи, которое отправляет данные в никуда.
SplitТолько io-util
Разделитель для метода split.
StderrТолько io-std
Дескриптор стандартного потока ошибок процесса.
StdinТолько io-std
Дескриптор стандартного потока ввода процесса.
StdoutТолько io-std
Дескриптор стандартного потока вывода процесса.
TakeТолько io-util
Поток для метода take.
WriteHalfТолько io-util
Записываемая половина значения, возвращённого функцией split.

Трейты

AsyncBufRead
Асинхронно читает байты.
AsyncBufReadExtТолько io-util
Трейт-расширение, добавляющий вспомогательные методы типам AsyncBufRead.
AsyncRead
Читает байты из источника.
AsyncReadExtТолько io-util
Читает байты из источника.
AsyncSeek
Асинхронно перемещается по байтам.
AsyncSeekExtТолько io-util
Трейт-расширение, добавляющий вспомогательные методы типам AsyncSeek.
AsyncWrite
Асинхронно записывает байты.
AsyncWriteExtТолько io-util
Записывает байты в приёмник.

Функции

copyТолько io-util
Асинхронно копирует всё содержимое средства чтения в средство записи.
copy_bidirectionalТолько io-util
Копирует данные в обоих направлениях между a и b.
copy_bidirectional_with_sizesТолько io-util
Копирует данные в обоих направлениях между a и b, используя буферы указанного размера.
copy_bufТолько io-util
Асинхронно копирует всё содержимое средства чтения в средство записи.
duplexТолько io-util
Создаёт пару DuplexStream, работающих как пара соединённых сокетов.
emptyТолько io-util
Создаёт значение, которое при чтении всегда возвращает EOF и игнорирует все записанные данные.
joinТолько io-util
Объединяет два значения, реализующих AsyncRead и AsyncWrite, в один дескриптор.
repeatТолько io-util
Создаёт экземпляр асинхронного средства чтения, бесконечно повторяющего один байт.
simplexТолько io-util
Создаёт однонаправленный буфер, работающий как канал в памяти.
sinkТолько io-util
Создаёт экземпляр асинхронного средства записи, которое успешно принимает все данные.
splitТолько io-util
Разделяет значение, реализующее AsyncRead + AsyncWrite, на отдельные дескрипторы AsyncRead и AsyncWrite.
stderrТолько io-std
Создаёт новый дескриптор стандартного потока ошибок текущего процесса.
stdinТолько io-std
Создаёт новый дескриптор стандартного потока ввода текущего процесса.
stdoutТолько io-std
Создаёт новый дескриптор стандартного потока вывода текущего процесса.

MIT License
Copyright © Tokio Contributors
https://docs.rs/tokio/1.53.1/tokio/io/index.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API