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
| Method | Description |
|---|---|
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_towithout ever callingbind(the OS assigns an ephemeral outbound port), but only bound sockets receive.
Tips
- Use
std.async.sleepto keep the receiver alive, same as TCP/HTTP servers. - UDP preserves message boundaries — one
send_toequals oneon_receivecall (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.