Структура TcpStream

#![allow(unused)]
fn main() {
pub struct TcpStream(_);
}

TCP-поток между локальным и удаленным сокетом.

После создания TcpStream путем подключения к удаленному узлу или accept подключения от TcpListener, данные могут быть отправлены через Write и получены через Read.

Клонирование TcpStream создаст новый дескриптор того же самого потока. Оба дескриптора могут использоваться для чтения и записи, и они будут совместно использовать один и тот же поток ввода-вывода.

Трансмиссия Control Protocol определяется в IETF RFC 793.

NOTE: Эта структура доступна в crate std для платформ wasm32-unknown-unknown, начиная с Rust 1.39.0, но в настоящее время она поддерживает только клиентские сокеты и не поддерживает серверные сокеты.

Примеры

use std::io::prelude::*;
use std::net::TcpStream;

fn main() -> std::io::Result<()> {
    // Подключение к порту 8080 localhost
    let mut stream = TcpStream::connect("127.0.0.1:8080")?;

    // Запись байтов в поток
    stream.write(&[1])?;
    stream.write_all(&[2, 3, 4])?;

    // Чтение ответа
    let mut buf = [0; 10];
    let n = stream.read(&mut buf)?;

    println!("Прочитано {} байт: {:?}", n, &buf[..n]);
    Ok(())
}

Методы

connect

#![allow(unused)]
fn main() {
pub fn connect<A: ToSocketAddrs>(addr: A) -> Result<TcpStream>
}

Открывает TCP-подключение к удаленному адресу.

addr - это адрес удаленного узла. Любой допустимый SocketAddr может быть передан, и если задано несколько адресов, будет предпринята попытка подключения к каждому из них по порядку, пока подключение не будет успешно установлено. Если ни одна из попыток не увенчается успехом, возвращается ошибка последней попытки.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;

if let Ok(stream) = TcpStream::connect("127.0.0.1:8080") {
    println!("Подключение установлено!");
} else {
    println!("Не удалось подключиться");
}
}

peer_addr

#![allow(unused)]
fn main() {
pub fn peer_addr(&self) -> Result<SocketAddr>
}

Возвращает адрес сокета удаленного узла этого подключения.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
println!("Подключен к {}", stream.peer_addr().unwrap());
}

local_addr

#![allow(unused)]
fn main() {
pub fn local_addr(&self) -> Result<SocketAddr>
}

Возвращает адрес локального сокета этого подключения.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
println!("Локальный адрес: {}", stream.local_addr().unwrap());
}

shutdown

#![allow(unused)]
fn main() {
pub fn shutdown(&self, how: Shutdown) -> Result<()>
}

Отключает часть подключения.

how определяет, какая часть подключения должна быть отключена:

  • Shutdown::Read - запрещает дальнейшие операции чтения
  • Shutdown::Write - запрещает дальнейшие операции записи
  • Shutdown::Both - запрещает как чтение, так и запись

Примеры

#![allow(unused)]
fn main() {
use std::net::{TcpStream, Shutdown};

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
stream.shutdown(Shutdown::Both).expect("Ошибка отключения");
}

try_clone

#![allow(unused)]
fn main() {
pub fn try_clone(&self) -> Result<TcpStream>
}

Создает новый независимо владеющий дескриптор того же самого потока.

Возвращенный TcpStream является ссылкой на тот же поток, что и этот объект. Оба дескриптора могут использоваться для чтения и записи, и они будут совместно использовать один и тот же поток ввода-вывода.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;
use std::thread;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
let stream_clone = stream.try_clone().unwrap();

thread::spawn(move || {
    // Использование stream_clone в другом потоке
});
}

set_read_timeout

#![allow(unused)]
fn main() {
pub fn set_read_timeout(&self, dur: Option<Duration>) -> Result<()>
}

Устанавливает таймаут чтения для этого потока.

Если значение равно None, то операции read будут блокироваться бесконечно. Если значение равно Some(Duration), то операции read будут таймаутировать по истечении указанного времени. Если таймаут происходит, возвращается ошибка TimedOut.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;
use std::time::Duration;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
stream.set_read_timeout(Some(Duration::from_secs(5))).expect("Не удалось установить таймаут чтения");
}

set_write_timeout

#![allow(unused)]
fn main() {
pub fn set_write_timeout(&self, dur: Option<Duration>) -> Result<()>
}

Устанавливает таймаут записи для этого потока.

Если значение равно None, то операции write будут блокироваться бесконечно. Если значение равно Some(Duration), то операции write будут таймаутировать по истечении указанного времени. Если таймаут происходит, возвращается ошибка TimedOut.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;
use std::time::Duration;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
stream.set_write_timeout(Some(Duration::from_secs(5))).expect("Не удалось установить таймаут записи");
}

read_timeout

#![allow(unused)]
fn main() {
pub fn read_timeout(&self) -> Result<Option<Duration>>
}

Возвращает текущий таймаут чтения для этого сокета.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;
use std::time::Duration;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
stream.set_read_timeout(Some(Duration::from_secs(5))).unwrap();
assert_eq!(stream.read_timeout().unwrap(), Some(Duration::from_secs(5)));
}

write_timeout

#![allow(unused)]
fn main() {
pub fn write_timeout(&self) -> Result<Option<Duration>>
}

Возвращает текущий таймаут записи для этого сокета.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;
use std::time::Duration;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
stream.set_write_timeout(Some(Duration::from_secs(5))).unwrap();
assert_eq!(stream.write_timeout().unwrap(), Some(Duration::from_secs(5)));
}

set_ttl

#![allow(unused)]
fn main() {
pub fn set_ttl(&self, ttl: u32) -> Result<()>
}

Устанавливает значение параметра IP_TTL для этого сокета.

Этот параметр устанавливает время жизни (Time-To-Live) для пакетов, отправленных из этого сокета.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
stream.set_ttl(100).expect("Не удалось установить TTL");
}

ttl

#![allow(unused)]
fn main() {
pub fn ttl(&self) -> Result<u32>
}

Получает значение параметра IP_TTL для этого сокета.

Для получения дополнительной информации смотрите set_ttl.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
stream.set_ttl(100).expect("Не удалось установить TTL");
assert_eq!(stream.ttl().unwrap_or(0), 100);
}

set_nodelay

#![allow(unused)]
fn main() {
pub fn set_nodelay(&self, nodelay: bool) -> Result<()>
}

Устанавливает значение параметра TCP_NODELAY для этого сокета.

Если установлено true, то пакеты будут отправляться как можно скорее, без задержки для объединения небольших пакетов.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
stream.set_nodelay(true).expect("Не удалось установить nodelay");
}

nodelay

#![allow(unused)]
fn main() {
pub fn nodelay(&self) -> Result<bool>
}

Получает значение параметра TCP_NODELAY для этого сокета.

Для получения дополнительной информации смотрите set_nodelay.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
stream.set_nodelay(true).expect("Не удалось установить nodelay");
assert_eq!(stream.nodelay().unwrap_or(false), true);
}

set_linger

#![allow(unused)]
fn main() {
pub fn set_linger(&self, linger: Option<Duration>) -> Result<()>
}

Устанавливает значение параметра SO_LINGER для этого сокета.

Этот параметр управляет поведением сокета при вызове close, когда в отправной очереди остались данные. Если установлено Some(Duration), то close будет блокироваться до тех пор, пока все данные не будут отправлены или не истечет указанное время. Если установлено None, то close вернется немедленно.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;
use std::time::Duration;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
stream.set_linger(Some(Duration::from_secs(5))).expect("Не удалось установить linger");
}

linger

#![allow(unused)]
fn main() {
pub fn linger(&self) -> Result<Option<Duration>>
}

Получает значение параметра SO_LINGER для этого сокета.

Для получения дополнительной информации смотрите set_linger.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;
use std::time::Duration;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
stream.set_linger(Some(Duration::from_secs(5))).unwrap();
assert_eq!(stream.linger().unwrap(), Some(Duration::from_secs(5)));
}

take_error

#![allow(unused)]
fn main() {
pub fn take_error(&self) -> Result<Option<Error>>
}

Получает значение параметра сокета SO_ERROR.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
if let Ok(Some(error)) = stream.take_error() {
    println!("Ошибка сокета: {}", error);
}
}

set_nonblocking

#![allow(unused)]
fn main() {
pub fn set_nonblocking(&self, nonblocking: bool) -> Result<()>
}

Переводит сокет в неблокирующий режим.

Если nonblocking равно true, то операции над сокетом, которые блокировали бы, будут возвращать ошибки вместо блокировки. Если nonblocking равно false, то сокет будет работать в блокирующем режиме.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;
use std::io;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
stream.set_nonblocking(true).expect("Не удалось установить неблокирующий режим");

let mut buf = [0; 10];
match stream.read(&mut buf) {
    Ok(n) => println!("Прочитано {} байт", n),
    Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
        // Данные пока не доступны
    }
    Err(e) => panic!("Неожиданная ошибка ввода-вывода: {}", e),
}
}

peek

#![allow(unused)]
fn main() {
pub fn peek(&self, buf: &mut [u8]) -> Result<usize>
}

Читает данные из потока без удаления их из буфера.

Эта функция работает как read, но данные, прочитанные через peek, остаются доступными для последующих вызовов read.

Примеры

#![allow(unused)]
fn main() {
use std::net::TcpStream;

let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
let mut buf = [0; 10];
let n = stream.peek(&mut buf).expect("Ошибка peek");
println!("Просмотрено {} байт: {:?}", n, &buf[..n]);
}

Трайт-реализации

Read, Write

#![allow(unused)]
fn main() {
impl Read for TcpStream
impl Write for TcpStream
}

Реализует операции чтения и записи для потока.

AsFd, AsRawFd, IntoRawFd

#![allow(unused)]
fn main() {
impl AsFd for TcpStream
impl AsRawFd for TcpStream  
impl IntoRawFd for TcpStream
}

Предоставляет доступ к низкоуровневому дескриптору файла.

From<TcpStream>

#![allow(unused)]
fn main() {
impl From<TcpStream> for Arc<TcpStream>
impl From<TcpStream> for Socket
}

Преобразует TcpStream в Arc<TcpStream> и Socket.

Debug

#![allow(unused)]
fn main() {
impl Debug for TcpStream
}

Реализует отладочное отображение для TcpStream.

Пример использования

use std::io::{Read, Write};
use std::net::TcpStream;
use std::thread;
use std::time::Duration;

fn main() -> std::io::Result<()> {
    let mut stream = TcpStream::connect("127.0.0.1:8080")?;
    
    // Настройка параметров сокета
    stream.set_nodelay(true)?;
    stream.set_ttl(64)?;
    stream.set_read_timeout(Some(Duration::from_secs(10)))?;
    
    // Отправка данных
    stream.write_all(b"Hello, server!")?;
    
    // Чтение ответа
    let mut response = String::new();
    stream.read_to_string(&mut response)?;
    
    println!("Получен ответ: {}", response);
    Ok(())
}