Reference · UDP
udp.listen
udp.listen(int, fn, map | null=) -> nullWhat 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
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:
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/>// 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 replyEdge cases
- The port is taken when the program runs, so one that is in use, or on an address the machine does not have, is an error at once.
- Packets reach
fin the order they came, one at a time; an error infis logged and the next packet goes on.fmay wait on the database orhttp.*without holding anyone up, and sees the program's globals. - A full queue drops its oldest packet, as UDP would; where packets come in bursts,
give
queueroom for the largest. fwritten with no parameter is called with none.- One program on a machine listens on a port; with
--instances, thequillo runoption that runs the program several times over (quillo run main.qwe --instances 4), the instances share the socket. With--reload(quillo run main.qwe --reload, reloading as the files change), a port still listened on stays open across the reload. See the options. - There is no multicast, and packets are plain: no DTLS.
- Opening a port is the
neteffect, as sending is: a function declaredwithwithoutnetcannot call it, and a policy whose[effects]leaves outnetrefuses it (`udp.listen` needs the net effect, which quillo.policy does not allow).
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.
udp.listen(0, (p) => p)line 1: `udp.listen` takes a port from 1 to 65535 first, got 0udp.listen(9000, (p) => p)udp.listen(9000, (p) => p)line 2: `udp.listen`: the program already listens on UDP port 9000udp.listen(9000, (p) => p, { queue: 0 })line 1: `udp.listen`: `queue` is a number of packets above 0Chaining
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.
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 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