Reference

std/network/udp

std/network/src/udp.trb

UDP: a UdpSocket sends and receives datagrams - each one whole, with the address it came from, or not at all (docs/design/NETWORK.md section 4, slice 5). A datagram is not a stream, so a socket is no Source: a receive answers one datagram and its sender, and a send hands one datagram to the operating system.

A socket is a handle of the runtime, like a TCP one, and is closed exactly once, by the close() the release of its owner runs.

type UdpSocket

shared type UdpSocket with Close

A UDP socket: bound to a local address, and - once UdpSocket.connect named one - connected to one peer. It has an identity, the operating system's socket, so it is a shared type, and it closes when the last reference to it goes.

using socket = UdpSocket.bind(SocketAddress(IpAddress.loopback, 0))?
socket.send("ping".bytes().toList(), to: server).await()?
const (answer, sender) = socket.receive().await()?

Nothing is promised of a datagram on its way: it may be lost, arrive twice or overtake another, and a protocol over UDP that needs more (DNS, QUIC) asks again after a timeout - receive().within(limit). What does arrive arrives whole, up to the largest datagram there is (65,507 bytes over IPv4).

fn bind

static fn bind(address: SocketAddress): Result<UdpSocket, NetworkError>

A socket bound to address. Port 0 asks the system for a free port, which UdpSocket.localAddress then says; an IPv6 address binds IPv6 only, on every system.

Errors

  • NetworkError that isAddressInUse() where another socket has the address.

fn localAddress

fn localAddress(): SocketAddress

Where it is bound, with the port the system chose where port 0 was asked for.

fn connect

fn connect(address: SocketAddress): Result<Void, NetworkError>

Connects the socket to one peer, which waits for nothing - no datagram goes over the network. From now on only the peer's datagrams arrive, UdpSocket.sendToPeer sends to it, and a peer whose port answers "unreachable" makes the next receive fail with isConnectionRefused(). Connecting again names another peer.

Errors

  • NetworkError for an address of the other IP version than the socket's, or port 0.

fn peerAddress

fn peerAddress(): SocketAddress?

The peer UdpSocket.connect named, or None for a socket that is not connected.

fn send

fn send(bytes: Bytes, to: SocketAddress): Task<Result<Void, NetworkError>>

Sends bytes as one datagram to to. Finishes once the operating system took it, which says nothing of whether it arrives. A connected socket sends to its peer only.

Errors

  • NetworkError for a datagram larger than the network carries, an address of the other IP version, or an address that is not the peer of a connected socket.

fn sendToPeer

fn sendToPeer(bytes: Bytes): Task<Result<Void, NetworkError>>

Sends bytes as one datagram to the peer UdpSocket.connect named.

Errors

  • NetworkError for a socket that is not connected, and for a datagram larger than the network carries.

fn receive

fn receive(): Task<Result<(Bytes, SocketAddress), NetworkError>>

The next datagram and where it came from. Waits until one arrives; a datagram that arrives while nobody receives waits in the socket, and a cancelled receive leaves it to the next one. A timeout is within: socket.receive().within(2.seconds()).await().

Errors

  • NetworkError that isConnectionRefused() on a connected socket whose peer's port is unreachable, and isClosed() once the socket was closed.

fn close

var fn close()

Closes the socket: a receive that waits fails with a closed socket. What the release of the socket runs.