Skip to main content

std.net — UDP

UDP is connectionless: there is no connect handshake. One socket both sends and receives. Bind a local port to receive, and send_to any destination to send.

Receiver — bind and print

var rx = std.net.udp()
rx.bind(7400) // bind local port
print("bound on", rx.port()) // actual port (useful when 0)
rx.on_receive(fn(data, host, port) {
print("from", host + ":" + port, "->", data)
})
std.async.sleep(2000) // stay alive to receive
rx.close()

Sender — no bind needed

var tx = std.net.udp()
tx.send_to("127.0.0.1", 7400, "ping from sender")
tx.close()

Run the receiver first, then the sender in another process — the receiver prints from 127.0.0.1:xxxxx -> ping from sender.

Reference

MethodDescription
bind(port)Bind a local port (default 0 = ephemeral) and start receiving; port() reports the actual bound port
port()Actual bound port
send_to(host, port, data)Send a datagram to host:port
on_receive(fn(data, host, port))Per datagram, with sender address
last_error()Most recent background error (recv failure or callback exception)
close()Release the socket

Differences from TCP

  • No connect/on_connect/disconnect — every datagram is independent.
  • No broadcast — send each destination separately.
  • Both sides can call send_to without ever calling bind (the OS assigns an ephemeral outbound port), but only bound sockets receive.

Tips

  • Use std.async.sleep to keep the receiver alive, same as TCP/HTTP servers.
  • UDP preserves message boundaries — one send_to equals one on_receive call (unlike raw TCP streams in other runtimes, though Scrii's TCP is already message-based).
  • Errors on the receive loop are recorded per endpoint and polled via udp.last_error() — see Concurrency — Errors.

See also

  • TCP — connected, message-based alternative
  • Overview