UDP
Send and receive a UDP datagram
UDP is connectionless: the sender fires a packet at an address and the receiver picks it up if it arrives. There is no session, no handshake, no retransmit. Statsd, syslog, NTP, and DNS all run on UDP for the same reason — minimum overhead when delivery guarantees aren’t worth the cost.
This example wires both ends together so it runs as a single program. The
collector binds to an OS-allocated port and waits with recv_from. The
client binds to its own ephemeral port and uses send_to to deliver a
metric. recv_from returns the byte count and the sender’s address.
use std::io;
use std::net::UdpSocket;
fn main() -> io::Result<()> {
let collector = UdpSocket::bind("127.0.0.1:0")?;
let collector_addr = collector.local_addr()?;
let client = UdpSocket::bind("127.0.0.1:0")?;
client.send_to(b"app.requests:1|c", collector_addr)?;
let mut buf = [0u8; 1500];
let (n, from) = collector.recv_from(&mut buf)?;
let metric = std::str::from_utf8(&buf[..n]).unwrap_or("<binary>");
println!("received {n} bytes from {from}: {metric}");
Ok(())
}
Join a UDP multicast group
Multicast lets one sender reach many receivers without addressing each one
individually. Service discovery (mDNS, SSDP) and announcement protocols rely
on it. A receiver binds to the multicast port and joins a group with
join_multicast_v4; the OS then delivers any datagram sent to that group
to every receiver that joined.
Multicast group addresses live in 224.0.0.0/4. Anything from 239.0.0.0 to
239.255.255.255 is reserved for private use — pick from there for in-house
apps.
use std::io;
use std::net::{Ipv4Addr, SocketAddr, UdpSocket};
fn main() -> io::Result<()> {
let group = Ipv4Addr::new(239, 0, 0, 100);
let port = 7878;
// Receiver: bind to the port, then join the group on every interface.
let receiver = UdpSocket::bind(SocketAddr::from(([0, 0, 0, 0], port)))?;
receiver.join_multicast_v4(&group, &Ipv4Addr::UNSPECIFIED)?;
// Sender: any local socket can send to the group address.
let sender = UdpSocket::bind("0.0.0.0:0")?;
sender.send_to(b"hello group", SocketAddr::new(group.into(), port))?;
let mut buf = [0u8; 64];
let (n, from) = receiver.recv_from(&mut buf)?;
println!("got {n} bytes from {from}");
Ok(())
}