Reference · UDP

udp.listen

signature
udp.listen(int, fn, map | null=) -> null

What it does

Takes UDP packets on a port: written at the top of a program, it binds the port when the program starts and calls f with each packet, { text, bytes, from: { host, port }, port, at }. text is the packet as text, or null when it is not UTF-8; bytes its bytes as a list of numbers; at when it came, in milliseconds since 1970. The options are host, the address to listen on (every IPv4 address, "0.0.0.0", unless given; "::" for IPv6 as well) and queue, how many packets wait while f is busy (10,000 unless given). The program then serves: a plain program with udp.listen in it does not end.

Examples

in a program
let readings = []udp.listen(9000, (p) => {    readings = readings + [json.parse(p.text)]   // pages with live(...) on it follow    udp.reply(p, "ok")                           // sent back from port 9000})udp.listen(514, (p) => db.exec("insert into syslog (host, line) values (?, ?)", p.from.host, p.text), {    host: "10.0.0.2",    queue: 50000,})

A whole round: the listener keeps each reading in a global that a page follows with live, and answers the sender. A device, or a script with udp.send, is the other side:

in a program
let readings = []udp.listen(9000, (p) => {    let r = json.parse(p.text)    if is_err(r) { return udp.reply(p, "bad") }    readings = readings + [{ from: p.from.host, ...r }]    udp.reply(p, "ok")})server fn load_readings() = readingscomponent Readings() {    state rows = live(load_readings)            // each new packet shows on every open page    <ul>{for r in rows => <li>{r.from}: {r.temp} C</li>}</ul>}route GET / = <Readings/>
in a program
// sensor.qwe, run with `quillo run sensor.qwe` while the program above servesudp.send("127.0.0.1", 9000, { temp: 21.5 })
echo '{"temp": 19}' | nc -u -w1 127.0.0.1 9000     # prints ok, the reply

Edge cases

in a program
udp.listen(9000, () => print("a packet"))udp.listen(9001, (p) => print(p.text ?? `${len(p.bytes)} bytes, not text`))

Errors

A port outside 1 to 65535, a second argument that is not a function, a bad host or queue, an option that does not exist, a port the program already listens on and a port that cannot be bound are runtime errors when the program starts, so it does not serve. There are no error values.

this one fails
udp.listen(0, (p) => p)
output
line 1: `udp.listen` takes a port from 1 to 65535 first, got 0
this one fails
udp.listen(9000, (p) => p)udp.listen(9000, (p) => p)
output
line 2: `udp.listen`: the program already listens on UDP port 9000
this one fails
udp.listen(9000, (p) => p, { queue: 0 })
output
line 1: `udp.listen`: `queue` is a number of packets above 0

Chaining

It gives null and is not piped. In f, udp.reply answers the sender, and channel.broadcast or a global that pages follow with live passes the packet on.

in a program
udp.listen(9000, (p) => {    let reading = json.parse(p.text) ?? reply_bad(p)    channel.broadcast("telemetry", { from: p.from.host, at: p.at, ...reading })})

See also

udp.reply, udp.send, channel.on, live, json.parse

Thread
8Useful? Like it, or add to its thread below.

Thread 0 posts

On udp.listen(): questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.

    Edit this page on GitHub · every example's output was made by running it (tools/refcheck.mjs) · questions on Discord or r/quillo