Структура SocketAddrV6

#![allow(unused)]
fn main() {
pub struct SocketAddrV6 { /* приватные поля */ }
}

Адрес интернет-сокса IPv6.

SocketAddrV6 включает в себя адрес IPv6, номер порта, а также поля flow information и scope ID, как определено в RFC 2553, Section 3.3.

Для получения дополнительной информации о полях flow information и scope ID смотрите IETF RFC 3493, Section 3.3 и IETF RFC 3542, Section 6.

См. также SocketAddr для типа, представляющий либо IPv4, либо IPv6 адрес сокета.

Представление в памяти

SocketAddrV6 имеет то же представление в памяти, что и соответствующая структура C sockaddr_in6.

Примеры

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

let socket = SocketAddrV6::new(
    Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
    8080,
    0,
    0,
);

assert_eq!(
    "[2001:db8::1]:8080".parse(),
    Ok(socket)
);
}

Методы

new

#![allow(unused)]
fn main() {
pub const fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6
}

Создает новый адрес сокета IPv6 из Ipv6Addr, номера порта, flow information и scope ID.

Примеры

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

let addr = SocketAddrV6::new(
    Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
    8080,
    0,
    0,
);
assert_eq!(addr.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
assert_eq!(addr.port(), 8080);
}

ip

#![allow(unused)]
fn main() {
pub const fn ip(&self) -> &Ipv6Addr
}

Возвращает IP-адрес, связанный с этим адресом сокета.

Примеры

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

let socket = SocketAddrV6::new(
    Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
    8080,
    0,
    0,
);
assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
}

port

#![allow(unused)]
fn main() {
pub const fn port(&self) -> u16
}

Возвращает номер порта, связанный с этим адресом сокета.

Примеры

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

let socket = SocketAddrV6::new(
    Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
    8080,
    0,
    0,
);
assert_eq!(socket.port(), 8080);
}

flowinfo

#![allow(unused)]
fn main() {
pub const fn flowinfo(&self) -> u32
}

Возвращает flow information, связанную с этим адресом сокета.

Эта информация соответствует полю sin6_flowinfo в структуре sockaddr_in6.

Примеры

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

let socket = SocketAddrV6::new(
    Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
    8080,
    42,
    0,
);
assert_eq!(socket.flowinfo(), 42);
}

scope_id

#![allow(unused)]
fn main() {
pub const fn scope_id(&self) -> u32
}

Возвращает scope ID, связанную с этим адресом сокета.

Эта информация соответствует полю sin6_scope_id в структуре sockaddr_in6 и используется для идентификации зоны ссылки для адресов link-local.

Примеры

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

let socket = SocketAddrV6::new(
    Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
    8080,
    0,
    3,
);
assert_eq!(socket.scope_id(), 3);
}

set_ip

#![allow(unused)]
fn main() {
pub fn set_ip(&mut self, new_ip: Ipv6Addr)
}

Устанавливает IP-адрес, связанный с этим адресом сокета.

Примеры

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

let mut socket = SocketAddrV6::new(
    Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
    8080,
    0,
    0,
);
socket.set_ip(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2));
assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2));
}

set_port

#![allow(unused)]
fn main() {
pub fn set_port(&mut self, new_port: u16)
}

Устанавливает номер порта, связанный с этим адресом сокета.

Примеры

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

let mut socket = SocketAddrV6::new(
    Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
    8080,
    0,
    0,
);
socket.set_port(9090);
assert_eq!(socket.port(), 9090);
}

set_flowinfo

#![allow(unused)]
fn main() {
pub fn set_flowinfo(&mut self, new_flowinfo: u32)
}

Устанавливает flow information, связанную с этим адресом сокета.

Примеры

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

let mut socket = SocketAddrV6::new(
    Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
    8080,
    0,
    0,
);
socket.set_flowinfo(123);
assert_eq!(socket.flowinfo(), 123);
}

set_scope_id

#![allow(unused)]
fn main() {
pub fn set_scope_id(&mut self, new_scope_id: u32)
}

Устанавливает scope ID, связанную с этим адресом сокета.

Примеры

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

let mut socket = SocketAddrV6::new(
    Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
    8080,
    0,
    0,
);
socket.set_scope_id(5);
assert_eq!(socket.scope_id(), 5);
}

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

From<SocketAddrV6>

#![allow(unused)]
fn main() {
impl From<SocketAddrV6> for SocketAddr
}

Преобразует SocketAddrV6 в SocketAddr.

Примеры

#![allow(unused)]
fn main() {
use std::net::{SocketAddr, SocketAddrV6, Ipv6Addr};

let socket_v6 = SocketAddrV6::new(
    Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
    8080,
    0,
    0,
);
let socket_addr = SocketAddr::from(socket_v6);
assert_eq!(socket_addr.ip().to_string(), "2001:db8::1");
assert_eq!(socket_addr.port(), 8080);
}

Display, Debug

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

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

Примеры

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

let socket = SocketAddrV6::new(
    Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
    8080,
    0,
    0,
);
println!("Адрес сокета: {}", socket); // "[2001:db8::1]:8080"
println!("Отладочная информация: {:?}", socket); // "[2001:db8::1]:8080"
}

PartialEq, Eq, PartialOrd, Ord, Hash

#![allow(unused)]
fn main() {
impl PartialEq for SocketAddrV6
impl Eq for SocketAddrV6
impl PartialOrd for SocketAddrV6
impl Ord for SocketAddrV6
impl Hash for SocketAddrV6
}

Реализует сравнение и хеширование для SocketAddrV6.

Примеры

#![allow(unused)]
fn main() {
use std::net::{SocketAddrV6, Ipv6Addr};
use std::collections::HashMap;

let socket1 = SocketAddrV6::new(
    Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
    8080,
    0,
    0,
);
let socket2 = SocketAddrV6::new(
    Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
    8080,
    0,
    0,
);
let socket3 = SocketAddrV6::new(
    Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2),
    8080,
    0,
    0,
);

assert_eq!(socket1, socket2);
assert_ne!(socket1, socket3);

let mut map = HashMap::new();
map.insert(socket1, "server1");
}

FromStr

#![allow(unused)]
fn main() {
impl FromStr for SocketAddrV6
}

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

Примеры

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

let socket = SocketAddrV6::from_str("[2001:db8::1]:8080").unwrap();
assert_eq!(socket.port(), 8080);
}

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

Создание и манипуляция адресами сокетов IPv6

use std::net::{SocketAddrV6, Ipv6Addr};

fn demonstrate_socketaddr_v6() {
    // Создание базового адреса сокета
    let mut socket = SocketAddrV6::new(
        Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
        8080,
        0,
        0,
    );
    
    println!("Исходный адрес: {}", socket);
    println!("  IP: {}", socket.ip());
    println!("  Порт: {}", socket.port());
    println!("  Flowinfo: {}", socket.flowinfo());
    println!("  Scope ID: {}", socket.scope_id());
    
    // Изменение полей
    socket.set_ip(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2));
    socket.set_port(9090);
    socket.set_flowinfo(123);
    socket.set_scope_id(5);
    
    println!("\nПосле изменений:");
    println!("  Адрес: {}", socket);
    println!("  IP: {}", socket.ip());
    println!("  Порт: {}", socket.port());
    println!("  Flowinfo: {}", socket.flowinfo());
    println!("  Scope ID: {}", socket.scope_id());
}

fn main() {
    demonstrate_socketaddr_v6();
}
use std::net::{SocketAddrV6, Ipv6Addr};

fn demonstrate_link_local() {
    // Link-local адреса требуют указания scope ID
    let link_local_sockets = [
        SocketAddrV6::new(
            Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
            8080,
            0,
            1, // scope ID для интерфейса 1
        ),
        SocketAddrV6::new(
            Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
            8080,
            0,
            2, // scope ID для интерфейса 2
        ),
    ];
    
    println!("Link-local адреса сокетов:");
    for socket in &link_local_sockets {
        println!("  Адрес: {}", socket);
        println!("    Scope ID: {}", socket.scope_id());
        println!("    Link-local: {}", socket.ip().is_unicast_link_local());
    }
    
    // Демонстрация, что разные scope ID создают разные сокеты
    let socket1 = &link_local_sockets[0];
    let socket2 = &link_local_sockets[1];
    
    println!("\nСравнение:");
    println!("  socket1 == socket2: {}", socket1 == socket2);
    println!("  socket1.ip() == socket2.ip(): {}", socket1.ip() == socket2.ip());
    println!("  socket1.scope_id() == socket2.scope_id(): {}", 
             socket1.scope_id() == socket2.scope_id());
}

fn main() {
    demonstrate_link_local();
}

Использование в сетевых операциях

use std::net::{TcpListener, UdpSocket, SocketAddrV6, Ipv6Addr};
use std::io;

fn create_ipv6_server() -> io::Result<()> {
    // Создание TCP слушателя на IPv6
    let socket_addr = SocketAddrV6::new(
        Ipv6Addr::UNSPECIFIED, // :: (все интерфейсы)
        8080,
        0,
        0,
    );
    
    let tcp_listener = TcpListener::bind(socket_addr)?;
    println!("TCP сервер слушает на: {}", tcp_listener.local_addr()?);
    
    // Создание UDP сокета на IPv6
    let udp_socket = UdpSocket::bind(socket_addr)?;
    println!("UDP сокет привязан к: {}", udp_socket.local_addr()?);
    
    Ok(())
}

fn connect_to_ipv6_server() -> io::Result<()> {
    let server_addr = SocketAddrV6::new(
        Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
        8080,
        0,
        0,
    );
    
    // Попытка подключения по TCP
    match std::net::TcpStream::connect(server_addr) {
        Ok(_stream) => println!("Успешное подключение к серверу"),
        Err(e) => println!("Ошибка подключения: {}", e),
    }
    
    Ok(())
}

fn main() -> io::Result<()> {
    create_ipv6_server()?;
    connect_to_ipv6_server()?;
    Ok(())
}

Преобразование между различными форматами

use std::net::{SocketAddr, SocketAddrV6, Ipv6Addr};

fn demonstrate_conversions() {
    // Создание SocketAddrV6
    let socket_v6 = SocketAddrV6::new(
        Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
        8080,
        123,
        5,
    );
    
    println!("SocketAddrV6: {}", socket_v6);
    println!("  IP: {}", socket_v6.ip());
    println!("  Порт: {}", socket_v6.port());
    println!("  Flowinfo: {}", socket_v6.flowinfo());
    println!("  Scope ID: {}", socket_v6.scope_id());
    
    // Преобразование в SocketAddr
    let socket_addr = SocketAddr::from(socket_v6);
    println!("\nПосле преобразования в SocketAddr:");
    println!("  SocketAddr: {}", socket_addr);
    println!("  IP: {}", socket_addr.ip());
    println!("  Порт: {}", socket_addr.port());
    println!("  is_ipv4(): {}", socket_addr.is_ipv4());
    println!("  is_ipv6(): {}", socket_addr.is_ipv6());
    
    // Обратное преобразование (если это IPv6)
    if let SocketAddr::V6(socket_v6_again) = socket_addr {
        println!("\nОбратное преобразование:");
        println!("  SocketAddrV6: {}", socket_v6_again);
        println!("  Flowinfo: {}", socket_v6_again.flowinfo());
        println!("  Scope ID: {}", socket_v6_again.scope_id());
    }
}

fn main() {
    demonstrate_conversions();
}

Парсинг из строки

use std::net::SocketAddrV6;
use std::str::FromStr;

fn demonstrate_parsing() {
    let test_cases = [
        "[2001:db8::1]:8080",
        "[::1]:80",
        "[fe80::1%eth0]:8080", // С scope ID
        "[2001:db8:85a3::8a2e:370:7334]:443",
    ];
    
    println!("Парсинг IPv6 адресов сокетов:");
    
    for test_case in &test_cases {
        match SocketAddrV6::from_str(test_case) {
            Ok(socket) => {
                println!("  ✓ '{}' -> {}", test_case, socket);
                println!("     IP: {}", socket.ip());
                println!("     Порт: {}", socket.port());
                println!("     Flowinfo: {}", socket.flowinfo());
                println!("     Scope ID: {}", socket.scope_id());
            }
            Err(e) => {
                println!("  ✗ '{}' -> Ошибка: {}", test_case, e);
            }
        }
        println!();
    }
}

fn main() {
    demonstrate_parsing();
}

Использование flow information

use std::net::{SocketAddrV6, Ipv6Addr};

fn demonstrate_flowinfo() {
    // Flow information используется для QoS (Quality of Service)
    // и управления трафиком в IPv6
    
    let sockets_with_flowinfo = [
        SocketAddrV6::new(
            Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
            8080,
            0x00000000, // Без flow information
            0,
        ),
        SocketAddrV6::new(
            Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
            8080,
            0x12345678, // С flow information
            0,
        ),
        SocketAddrV6::new(
            Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
            8080,
            0x80000000, // Flow label для реального времени
            0,
        ),
    ];
    
    println!("Адреса сокетов с flow information:");
    
    for socket in &sockets_with_flowinfo {
        println!("  Адрес: {}", socket);
        println!("    Flowinfo: 0x{:08x}", socket.flowinfo());
        
        // Анализ flow information
        let flowinfo = socket.flowinfo();
        let flow_label = (flowinfo >> 12) & 0x000FFFFF; // 20 бит flow label
        let traffic_class = (flowinfo >> 4) & 0x000000FF; // 8 бит traffic class
        
        println!("    Flow Label: 0x{:05x}", flow_label);
        println!("    Traffic Class: 0x{:02x}", traffic_class);
        
        if flow_label != 0 {
            println!("    → Пакеты с flow label могут получать специальную обработку");
        }
    }
}

fn main() {
    demonstrate_flowinfo();
}

Особенности IPv6 сокетов

Flow Information

  • Используется для QoS и управления трафиком
  • Содержит 20-битный flow label и 8-битный traffic class
  • Помогает идентифицировать потоки пакетов для специальной обработки

Scope ID

  • Требуется для link-local адресов (fe80::/10)
  • Идентифицирует конкретный сетевой интерфейс
  • Разные scope ID создают разные сокеты, даже с одинаковым IP

Представление в памяти

Совместимо с системной структурой sockaddr_in6, что позволяет напрямую использовать в системных вызовах.