Структура 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(); }
Работа с link-local адресами и scope ID
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, что позволяет напрямую использовать в системных вызовах.