🎓 A1Learner
🔍

Rust Socket Addresses

A SocketAddr is one value that holds an IP address and a port. A SocketAddr can be built from its pieces, and its pieces can be read back out.

Turn text into an address

One parse call turns the written form into a value:

let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();

Read the pieces back out

println!("ip = {}", addr.ip());
println!("port = {}", addr.port());
println!("ipv4 = {}", addr.is_ipv4());

Build one from pieces

No text is needed. Four bytes and a port do the job:

let built = SocketAddr::from(([127, 0, 0, 1], 8080));
println!("built = {}", built);

Ask what kind of address it is

println!("v4 loopback = {}", Ipv4Addr::LOCALHOST.is_loopback());
println!("v6 loopback = {}", Ipv6Addr::LOCALHOST.is_loopback());
println!("any is unspecified = {}", Ipv4Addr::UNSPECIFIED.is_unspecified());

Bind narrow or bind wide

127.0.0.1 hears only this machine. 0.0.0.0 hears every face. Its ip() reads back as unspecified:

let wide = TcpListener::bind("0.0.0.0:0").unwrap();
println!("wide bind is unspecified = {}", wide.local_addr().unwrap().ip().is_unspecified());

Example

use std::net::{SocketAddr, TcpListener};

fn main() {
    let texts = ["127.0.0.1:8080", "[::1]:9000", "not an address"];
    for text in texts {
        match text.parse::<SocketAddr>() {
            Ok(addr) => println!("{text} -> ip {}, port {}, ipv6 {}", addr.ip(), addr.port(), addr.is_ipv6()),
            Err(_) => println!("{text} -> not an address"),
        }
    }
    let listener = TcpListener::bind("127.0.0.1:0").unwrap();
    let local = listener.local_addr().unwrap();
    println!("bound to ip {} on a free port = {}", local.ip(), local.port() > 0);
}

Key points

  • SocketAddr: one value that holds an IP address and a port together
  • Use text.parse::<SocketAddr>() to turn written text into an address.
  • Text that is not an address gives an Err
  • Use addr.ip() and addr.port() to read the pieces back out
  • Use SocketAddr::from(([127, 0, 0, 1], 8080)) to build an address from pieces, with no text to parse
  • Binding to 0.0.0.0 claims every network face of this machine.
  • Binding to 127.0.0.1 claims this machine only

In this example, three texts meet parse::<SocketAddr>(). The first is a plain IPv4 address. The second is IPv6, so it wears square brackets. The third is not an address at all. It lands in the Err arm and prints a plain message. Then a listener binds 127.0.0.1:0. Port 0 lets the system pick a free port. The program prints the chosen ip. It checks only that the port is real, not which port it is.

Note

IPv6 text wears square brackets: [::1]:8080.

The brackets keep the colons of the address apart from the colon of the port.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

What does binding a listener to 0.0.0.0 ask for?