将字符串转换为SocketAddr

30

在 Rust 1.0 之前的版本中,我可以使用 from_str()String 转换为 SocketAddr,但该函数已不再存在。在 Rust 1.0 中该如何实现这个功能?

let server_details = reader.read_line().ok().expect("Something went wrong").as_slice().trim();

let server: SocketAddr = from_str(server_details);

let mut s = BufferedStream::new((TcpStream::connect(server).unwrap()));
3个回答

43

from_str被重命名为parse,现在是您可以在字符串上调用的方法:

use std::net::SocketAddr;

fn main() {
    let server_details = "127.0.0.1:80";
    let server: SocketAddr = server_details
        .parse()
        .expect("Unable to parse socket address");
    println!("{:?}", server);
}

如果你想要能够将DNS条目解析为IPv{4,6}地址,你可能希望使用ToSocketAddrs

use std::net::{TcpStream, ToSocketAddrs};

fn main() {
    let server_details = "stackoverflow.com:80";
    let server: Vec<_> = server_details
        .to_socket_addrs()
        .expect("Unable to resolve domain")
        .collect();
    println!("{:?}", server);

    // Even easier, if you want to connect right away:
    TcpStream::connect(server_details).expect("Unable to connect to server");
}

to_socket_addrs 返回一个迭代器,因为单个DNS条目可以扩展为多个IP地址!请注意,由于网络访问在playground中被禁用,因此此代码将无法在playground中工作;您需要在本地尝试。


10
我会在 Shepmaster 的回答中详细解释 "如果您想立即连接" 的评论。
请注意,您不需要事先将字符串转换为 SocketAddr 以便连接到某个地址。 TcpStream::connect() 和其他接受地址的函数被定义为接受 ToSocketAddr trait 的实例:
fn connect<T: ToSocketAddr>(addr: T) -> TcpStream { ... }

这意味着您可以直接将字符串传递给connect(),无需进行任何转换:
TcpStream::connect("stackoverflow.com:80")

此外,在预先将字符串转换为SocketAddr之前最好不要这样做,因为域名可能会解析为多个地址,并且TcpStream有特殊的逻辑来处理此类情况。

字符串是从标准输入中获取的主机:端口组合。地址每次都会改变。我非常确定它需要被转换。 - user3746744
抱歉,我不明白你的意思。当你只想连接到某个东西时,你不需要手动调用 to_socket_addr()。而且你所说的地址每次改变是什么意思? - Vladimir Matveev
@vladimir-matveev 的 ToSocketAddr 函数期望 (除其他参数外) 字符串格式为 Name:Port 或 Address:Port,例如 "www.example.com".to_socketaddr 或 "192.168.0.1:80".to_socketaddr。 - HerbM

1
在拍手中,你可以这样解析:

    #[derive(Clone, Debug, Parser)]
    #[clap(author, version, about, long_about = None)]
    struct Args {
        #[arg(long, env, default_value = "demo.com:8080", value_parser = resolve_host)]
        target_host: SocketAddr,
    }
        
    fn resolve_host(hostname_port: &str) -> io::Result<SocketAddr> {
        let socketaddr = hostname_port.to_socket_addrs()?.next().ok_or_else(|| {
            io::Error::new(
                io::ErrorKind::AddrNotAvailable,
                format!("Could not find destination {hostname_port}"),
            )
        })?;
        Ok(socketaddr)
    }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接