rust - 如何检测源地址是IPv4还是IPv6

标签 rust

有什么方法可以检测源地址是 IPv4 还是 IPv6?
我写了类似的东西

let listener = TcpListener::bind("[::]:33333").unwrap();
for res in listener.incoming() {
  match res {
    Ok(stream) => {thread::spawn(move||{handler(stream);},
    Err(_) => {println!("error");},
  }
}

处理函数如下:

fn handler(mut stream: TcpStream) -> Result<(),Error> {
  if stream.peer_addr().unwrap().is_ipv4() {
    println!("peer is IPv4");
  }
  else {
    println!("peer is IPv6");
  }

在处理函数中,我使用stream.peer_addr().unwrap().is_ipv4()来查找对等地址是IPv4还是IPv6。但所有地址都是 IPv6。当我连接到 127.0.0.1 的服务器时,对等地址是 IPv4 映射的 IPv6 地址:V6([::ffff:127.0.0.1]:33333)。如果服务器绑定(bind)到 0.0.0.0:33333,我无法连接到其 IPv6 地址(例如::1)。无论如何,服务器是否接受来自 IPv4 和 IPv6 对等方的连接,并且不使用 IPv4 映射的 IPv6 地址?我使用的是 Ubuntu 20.04.1。谢谢你,

最佳答案

不,它们是不兼容的协议(protocol),您必须将 IPv4 映射到 IPv6。

IPv6 不向后兼容,但有映射到 IPv6 的 IPv4 的特殊表示。

80 位设置为 0,后跟 16 位设置为 1,后跟 32 位,这就是 IPv4 地址。

换句话说,你可以检查它的 ipv4 是否映射到 ipv6,如下所示:

fn is_mapped_to_ipv6(addr: SocketAddr) -> bool {
    match addr {
        SocketAddr::V6(v6) => match v6.ip().segments() {
            // 5 * 16 `0` bits, 16 `1` bits, leftover is actual IPv4 addr
            [0, 0, 0, 0, 0, 0xFFFF, ..] => true,
            _ => false,
        },
        _ => false,
    }
}

关于rust - 如何检测源地址是IPv4还是IPv6,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63742236/

相关文章:

Rust 中的嵌套常量

memory - 如何在lazy_static 中释放内存?

multithreading - 如何将 Tokio 线程池限制为一定数量的 native 线程?

types - 为什么 Vec<T> 不实现 Display 特性?

rust - 如何高效地将可显示项插入字符串?

rust - 对外部用户弃用,但允许我吗?

rust - 如何创建 FFI 绑定(bind)到需要 OR 字节的 C 函数?

rust - Rocket 无法编译

unicode - 这个混合字符串如何在 unicode 单词边界上拆分

random - 如何将变异循环转换为功能样式?